-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enh: basic project structure and simple PoC
- Loading branch information
Showing
10 changed files
with
301 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
NEO4J_URL="neo4j://localhost:7687" | ||
PASSWORD=IAMmeIAMme!1! | ||
NEO4J_AUTH="neo4j/${PASSWORD}" | ||
NEO4J_URL=neo4j://localhost:7687 | ||
NEO4J_USER=neo4j | ||
NEO4J_PASS=IAMmeIAMme!1! | ||
NEO4J_AUTH="${NEO4J_USER}/${NEO4J_PASS}" | ||
NEO4J_server_memory_heap_initial__size=12G | ||
NEO4J_server_memory_heap_max__size=16G | ||
NEO4J_server_memory_pagecache_size=12G | ||
NEO4J_server_memory_pagecache_size=12G | ||
OKTA_CLIENT_ORGURL=yourtenant.okta.com | ||
OKTA_CLIENT_TOKEN="00SOMETHINGWRONG" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
dist | ||
iamme* | ||
IAMme-IAMme* | ||
*.sarif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package cmd | ||
|
||
import ( | ||
"IAMme-IAMme/pkg/app" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
var usersCmd = &cobra.Command{ | ||
Use: "dump", | ||
Short: "Fetch Okta info and store them in Neo4j", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
oktaNeo4jApp := app.NewOktaNeo4jApp(clients.okta, clients.neo4j) | ||
oktaNeo4jApp.Dump() | ||
}, | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(usersCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package cmd | ||
|
||
import ( | ||
"IAMme-IAMme/pkg/infra/neo4j" | ||
"IAMme-IAMme/pkg/infra/okta" | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
type clients_type struct { | ||
okta okta.OktaClient | ||
neo4j neo4j.Neo4jClient | ||
} | ||
|
||
var clients *clients_type | ||
var rootCmd = &cobra.Command{ | ||
Use: "iamme-iamme", | ||
Short: "A CLI tool to interact with Okta and Neo4j", | ||
} | ||
|
||
func Execute(oktaClient okta.OktaClient, neo4jClient neo4j.Neo4jClient) { | ||
clients = &clients_type{ | ||
oktaClient, | ||
neo4jClient, | ||
} | ||
if err := rootCmd.Execute(); err != nil { | ||
fmt.Println(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,61 @@ | ||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= | ||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= | ||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= | ||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= | ||
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= | ||
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= | ||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= | ||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= | ||
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= | ||
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= | ||
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= | ||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= | ||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | ||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | ||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | ||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= | ||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= | ||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= | ||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= | ||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/neo4j/neo4j-go-driver/v5 v5.14.0 h1:5x3vD4HkXQIktlG63jSG8v9iweGjmObIPU7Y9U0ThUI= | ||
github.com/neo4j/neo4j-go-driver/v5 v5.14.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k= | ||
github.com/okta/okta-sdk-golang/v2 v2.20.0 h1:EDKM+uOPfihOMNwgHMdno+NAsIfyXkVnoFAYVPay0YU= | ||
github.com/okta/okta-sdk-golang/v2 v2.20.0/go.mod h1:FMy5hN5G8Rd/VoS0XrfyPPhIfOVo78ZK7lvwiQRS2+U= | ||
github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627 h1:pSCLCl6joCFRnjpeojzOpEYs4q7Vditq8fySFG5ap3Y= | ||
github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= | ||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= | ||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= | ||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= | ||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= | ||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,18 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"IAMme-IAMme/cmd" | ||
"IAMme-IAMme/pkg/infra/neo4j" | ||
"IAMme-IAMme/pkg/infra/okta" | ||
"log" | ||
|
||
"github.com/joho/godotenv" | ||
) | ||
|
||
func main() { | ||
fmt.Println("IAMme IAMme") | ||
envFile, err := godotenv.Read(".env") | ||
if err != nil { | ||
log.Fatalln(err.Error()) | ||
} | ||
cmd.Execute(okta.NewOktaClient(envFile["OKTA_CLIENT_ORGURL"], envFile["OKTA_CLIENT_TOKEN"]), neo4j.NewNeo4jClient(envFile["NEO4J_URL"], envFile["NEO4J_USER"], envFile["NEO4J_PASS"])) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package app | ||
|
||
import ( | ||
"IAMme-IAMme/pkg/infra/neo4j" | ||
"IAMme-IAMme/pkg/infra/okta" | ||
"context" | ||
"log" | ||
"strings" | ||
|
||
neo4jSdk "github.com/neo4j/neo4j-go-driver/v5/neo4j" | ||
) | ||
|
||
type OktaNeo4jApp interface { | ||
Dump() | ||
} | ||
|
||
func NewOktaNeo4jApp(oktaClient okta.OktaClient, neo4jClient neo4j.Neo4jClient) OktaNeo4jApp { | ||
return &oktaNeo4jApp{ | ||
oktaClient: oktaClient, | ||
neo4jClient: neo4jClient, | ||
} | ||
} | ||
|
||
type oktaNeo4jApp struct { | ||
oktaClient okta.OktaClient | ||
neo4jClient neo4j.Neo4jClient | ||
} | ||
|
||
func (a *oktaNeo4jApp) Dump() { | ||
users, err := a.oktaClient.GetUsers() | ||
if err != nil { | ||
log.Println(err.Error()) | ||
} | ||
|
||
userParams := make([]map[string]interface{}, 0) | ||
for _, user := range users { | ||
userParams = append(userParams, map[string]interface{}{ | ||
"userId": user.Id, | ||
"status": user.Status, | ||
"firstName": (*user.Profile)["firstName"], | ||
"lastName": (*user.Profile)["lastName"], | ||
}) | ||
} | ||
|
||
session := a.neo4jClient.Connect() | ||
ctx := context.TODO() | ||
query := buildDynamicQuery(userParams) | ||
_, err = session.ExecuteWrite(ctx, func(tx neo4jSdk.ManagedTransaction) (interface{}, error) { | ||
_, err := tx.Run(ctx, query, map[string]interface{}{ | ||
"userParams": userParams, | ||
}) | ||
|
||
if err != nil { | ||
panic(err) | ||
} | ||
return nil, err | ||
}) | ||
if err != nil { | ||
log.Fatalln(err.Error()) | ||
} | ||
} | ||
|
||
// TODO: this is ugly AF | ||
func buildDynamicQuery(userParams []map[string]interface{}) string { | ||
var queryBuilder strings.Builder | ||
|
||
queryBuilder.WriteString("UNWIND $userParams as user\n") | ||
queryBuilder.WriteString("CREATE (u:User {\n") | ||
|
||
fields := userParams[0] | ||
|
||
i := 0 | ||
for field := range fields { | ||
queryBuilder.WriteString(fieldKeyToCypherProperty(field) + ": user." + fieldKeyToCypherProperty(field)) | ||
i++ | ||
if i < len(fields) { | ||
queryBuilder.WriteString(",\n") | ||
} | ||
} | ||
|
||
queryBuilder.WriteString("\n})\n") | ||
queryBuilder.WriteString("RETURN u\n") | ||
|
||
return queryBuilder.String() | ||
} | ||
|
||
// TODO: this is ugly AF | ||
func fieldKeyToCypherProperty(key interface{}) string { | ||
keyStr, ok := key.(string) | ||
if !ok { | ||
panic("Invalid field key") | ||
} | ||
|
||
return keyStr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package neo4j | ||
|
||
import ( | ||
"context" | ||
"log" | ||
|
||
"github.com/neo4j/neo4j-go-driver/v5/neo4j" | ||
) | ||
|
||
// Neo4jClient is an interface for interacting with the Neo4j database. | ||
type Neo4jClient interface { | ||
Connect() neo4j.SessionWithContext | ||
Close() error | ||
} | ||
|
||
// Session is an interface for a Neo4j database session. | ||
type Session interface { | ||
Run(cypher string, params map[string]interface{}) Result | ||
Close() error | ||
} | ||
|
||
// Result is an interface for a Neo4j query result. | ||
type Result interface { | ||
Consume() (int, error) | ||
} | ||
|
||
type neo4jClient struct { | ||
driver neo4j.DriverWithContext | ||
} | ||
|
||
func NewNeo4jClient(dbUri, username, password string) Neo4jClient { | ||
driver, err := neo4j.NewDriverWithContext(dbUri, neo4j.BasicAuth(username, password, "")) | ||
if err != nil { | ||
log.Fatalln("Invalid Neo4j login", err.Error()) | ||
} | ||
return &neo4jClient{ | ||
driver: driver, | ||
} | ||
} | ||
|
||
func (c *neo4jClient) Connect() neo4j.SessionWithContext { | ||
return c.driver.NewSession(context.TODO(), neo4j.SessionConfig{ | ||
AccessMode: neo4j.AccessModeWrite, | ||
}) | ||
} | ||
|
||
func (c *neo4jClient) Close() error { | ||
return c.driver.Close(context.TODO()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package okta | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/okta/okta-sdk-golang/v2/okta" | ||
) | ||
|
||
// OktaClient is an interface for interacting with Okta resources. | ||
type OktaClient interface { | ||
GetUsers() ([]*okta.User, error) | ||
GetGroups() ([]*okta.Group, error) | ||
} | ||
|
||
type oktaClient struct { | ||
oktaClient *okta.Client | ||
context context.Context | ||
} | ||
|
||
func NewOktaClient(orgUrl, apiKey string) OktaClient { | ||
ctx, client, err := okta.NewClient(context.Background(), okta.WithOrgUrl(fmt.Sprintf("https://%s", orgUrl)), okta.WithToken(apiKey)) | ||
if err != nil { | ||
log.Fatalln("Invalid Okta login", err.Error()) | ||
} | ||
return &oktaClient{ | ||
oktaClient: client, | ||
context: ctx, | ||
} | ||
} | ||
|
||
func (c *oktaClient) GetUsers() ([]*okta.User, error) { | ||
users, _, err := c.oktaClient.User.ListUsers(context.TODO(), nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return users, nil | ||
} | ||
|
||
func (c *oktaClient) GetGroups() ([]*okta.Group, error) { | ||
groups, _, err := c.oktaClient.Group.ListGroups(context.TODO(), nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return groups, nil | ||
} |