Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LaunchDarkly Token Analyzer #3948

Merged
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
36e64af
initial commit
kashifkhan0771 Feb 21, 2025
1c92298
initial commit
kashifkhan0771 Feb 24, 2025
f143fa8
initial commit
kashifkhan0771 Feb 25, 2025
b840782
inital commit
kashifkhan0771 Feb 26, 2025
aab2c0a
initial working structure for launchdarkly analyzer
kashifkhan0771 Feb 27, 2025
9806026
added more apis
kashifkhan0771 Mar 4, 2025
cc2ac00
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 4, 2025
8ff00ae
added test cases
kashifkhan0771 Mar 4, 2025
745868e
removed imposter print statement
kashifkhan0771 Mar 4, 2025
6d3b8fa
updated some code
kashifkhan0771 Mar 4, 2025
6902b03
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 5, 2025
746e4fb
removed id from printResources
kashifkhan0771 Mar 5, 2025
8452bdd
added nabeel suggestion and set analysis info
kashifkhan0771 Mar 5, 2025
d445b25
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 5, 2025
25356be
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 6, 2025
4235470
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 6, 2025
143947a
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 7, 2025
8a0561a
resolved ahrav comments
kashifkhan0771 Mar 7, 2025
deccdd9
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 7, 2025
8d6265f
Merge branch 'main' into feat/oss-95-launchdarkly-analyzer
kashifkhan0771 Mar 10, 2025
08cdc2f
resolved ahrav comments
kashifkhan0771 Mar 10, 2025
47cdd0c
implemented ahrav's suggestion 🔥
kashifkhan0771 Mar 10, 2025
1c61fce
resolved linter error
kashifkhan0771 Mar 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
initial working structure for launchdarkly analyzer
  • Loading branch information
kashifkhan0771 committed Feb 27, 2025
commit aab2c0abe2b884ba1a89b1ebf826399395c3a951
89 changes: 76 additions & 13 deletions pkg/analyzer/analyzers/launchdarkly/launchdarkly.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
package launchdarkly

import (
"errors"
"fmt"
"os"

@@ -24,7 +25,18 @@ func (a Analyzer) Type() analyzers.AnalyzerType {
}

func (a Analyzer) Analyze(_ context.Context, credInfo map[string]string) (*analyzers.AnalyzerResult, error) {
return nil, nil
// check if the `key` exist in the credentials info
key, exist := credInfo["key"]
if !exist {
return nil, errors.New("key not found in credentials info")
}

info, err := AnalyzePermissions(a.Cfg, key)
if err != nil {
return nil, err
}

return secretInfoToAnalyzerResult(info), nil
}

func AnalyzeAndPrintPermissions(cfg *config.Config, token string) {
@@ -61,12 +73,73 @@ func AnalyzePermissions(cfg *config.Config, token string) (*SecretInfo, error) {

// capture resources in secretInfo
if err := CaptureResources(client, token, secretInfo); err != nil {
return nil, fmt.Errorf("failed to fetch caller identity: %v", err)
return nil, fmt.Errorf("failed to fetch resources: %v", err)
}

return secretInfo, nil
}

// secretInfoToAnalyzerResult translate secret info to Analyzer Result
func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
if info == nil {
return nil
}

result := analyzers.AnalyzerResult{
AnalyzerType: analyzers.AnalyzerTypeElevenLabs,
Metadata: map[string]any{},
Bindings: make([]analyzers.Binding, 0),
}

// extract information from resource to create bindings and append to result bindings
for _, resource := range info.Resources {
binding := analyzers.Binding{
Resource: *secretInforesourceToAnalyzerResource(resource),
Permission: analyzers.Permission{
Value: getPermissionType(info.User.Token),
},
}

binding.Resource.Parent = secretInforesourceToAnalyzerResource(*resource.ParentResource)

result.Bindings = append(result.Bindings, binding)

}

return &result
}

// secretInforesourceToAnalyzerResource translate secret info resource to analyzer resource for binding
func secretInforesourceToAnalyzerResource(resource Resource) *analyzers.Resource {
analyzerRes := analyzers.Resource{
FullyQualifiedName: resource.ID,
Name: resource.Name,
Type: resource.Type,
Metadata: map[string]any{},
}

for key, value := range resource.MetaData {
analyzerRes.Metadata[key] = value
}

return &analyzerRes
}

// getPermissionType return what type of permission is assigned to token
func getPermissionType(token Token) string {
permission := ""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (potential alternative solution): A switch is a little more idiomatic, but totally up to you.

Ex:

switch {
case token.Role != "":
    return token.Role
case token.hasInlineRole():
    return "Inline Policy"
case token.hasCustomRoles():
    return "Custom Roles"
default:
    return ""
}


if token.Role != "" {
permission = token.Role
} else if token.hasInlineRole() {
permission = "Inline Policy"
} else if token.hasCustomRoles() {
permission = "Custom Roles"
}

return permission
}

// printUser print User information from secret info to cli
func printUser(user User) {
// print caller information
@@ -112,17 +185,7 @@ func printUser(user User) {
// printPermissionsType print permissions type token has
func printPermissionsType(token Token) {
// print permission type. It can be either admin, writer, reader or has inline policy or any custom roles assigned
permission := ""

if token.Role != "" {
permission = token.Role
} else if token.hasInlineRole() {
permission = "Inline Policy"
} else if token.hasCustomRoles() {
permission = "Custom Roles"
}

color.Green("\n[i] Permission Type: %s", permission)
color.Green("\n[i] Permission Type: %s", getPermissionType(token))
}

func printResources(resources []Resource) {
51 changes: 8 additions & 43 deletions pkg/analyzer/analyzers/launchdarkly/models.go
Original file line number Diff line number Diff line change
@@ -6,11 +6,14 @@
MetadataKey = "key"

// resource types
applicationType = "Application"
repositoryType = "Repository"
projectType = "Project"
environmentType = "Environment"
experimentType = "Expirement"
applicationKey = "Application"
repositoryKey = "Repository"
projectKey = "Project"
environmentKey = "Environment"
experimentKey = "Expirement"

Check failure on line 13 in pkg/analyzer/analyzers/launchdarkly/models.go

GitHub Actions / golangci-lint

`Expirement` is a misspelling of `Experiment` (misspell)
holdoutsKey = "Holdout"
membersKey = "Member"
destinationsKey = "Destination"
)

type SecretInfo struct {
@@ -80,28 +83,6 @@
MetaData map[string]string
}

// addPermission add a new permission to secret info permissions list.
func (s *SecretInfo) addPermission(perm string) {
s.mu.Lock()
defer s.mu.Unlock()

s.Permissions = append(s.Permissions, perm)
}

// hasPermission checks if a particular permission exist in secret info permissions list.
func (s *SecretInfo) hasPermission(perm string) bool {
s.mu.RLock()
defer s.mu.RUnlock()

for _, permission := range s.Permissions {
if permission == perm {
return true
}
}

return false
}

// appendResources append resource to secret info resources list
func (s *SecretInfo) appendResource(resource Resource) {
s.mu.Lock()
@@ -125,22 +106,6 @@
return resources
}

// getResourceByID returns a copy of the resource matching the given ID, or nil if not found.
func (s *SecretInfo) getResourceByID(id string) *Resource {
s.mu.RLock()
defer s.mu.RUnlock()

for _, resource := range s.Resources {
if resource.ID == id {
// return a copy of the resource to avoid accidently making changes in the actual resource
copyResource := resource
return &copyResource
}
}

return nil
}

// hasCustomRoles check if token has any custom roles assigned
func (t Token) hasCustomRoles() bool {
return len(t.CustomRoles) > 0
@@ -152,7 +117,7 @@
}

// isAllowed check if policy allow the statement
func (p Policy) isAllowed() bool {

Check failure on line 120 in pkg/analyzer/analyzers/launchdarkly/models.go

GitHub Actions / golangci-lint

func `Policy.isAllowed` is unused (unused)
return p.Effect == "allow"
}

Loading
Oops, something went wrong.
Loading
Oops, something went wrong.
You are viewing a condensed version of this merge commit. You can view the full changes here.