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

Resurrect Workload Identity Work #6802

Merged
merged 24 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a6a2406
Resurrect Workload Identity Work
ledbutter Jun 3, 2024
14c737a
docs/content/monitoring: Remove missing prometheus metric `go_memstat…
philipaconrad Jun 3, 2024
0f23dc5
docs: add vs code and zed to ecosystem page (#6788)
charlieegan3 Jun 4, 2024
90faf1d
docs: add flipt blog to their ecosystem page (#6789)
charlieegan3 Jun 4, 2024
ab7af86
Fix spelling and grammar of an HTTP (#6786)
jdbaldry Jun 4, 2024
4182e5a
build: bump golang 1.22.3 -> 1.22.4
srenatus Jun 5, 2024
95c543f
build(deps): bump golang.org/x/net from 0.25.0 to 0.26.0
dependabot[bot] Jun 5, 2024
3e0efe7
build(deps): bump github.com/containerd/containerd from 1.7.17 to 1.7.18
dependabot[bot] Jun 5, 2024
30b34df
build(deps): bump aquasecurity/trivy-action from 0.21.0 to 0.22.0
dependabot[bot] Jun 7, 2024
c351636
Fix tests
ledbutter Jun 10, 2024
df7538e
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 10, 2024
15b6026
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 11, 2024
0fcf5df
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 12, 2024
4296e10
Rename map for clarity
ledbutter Jun 14, 2024
0dc9d3b
Add Rest Tests
ledbutter Jun 14, 2024
598c079
Bump version for distinct images
ledbutter Jun 14, 2024
b275279
Version test no worky
ledbutter Jun 14, 2024
8a8091e
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 17, 2024
ccc7a99
Need to set Client ID
ledbutter Jun 18, 2024
f524ec0
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 19, 2024
6dfc609
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 25, 2024
7a6992b
Add Workload Identity Documentation
ledbutter Jun 27, 2024
b33b5bf
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jun 27, 2024
23a9f9a
Merge branch 'main' into azureWorkloadIdentity
ledbutter Jul 1, 2024
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
75 changes: 68 additions & 7 deletions plugins/rest/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import (
const (
// Default to s3 when the service for sigv4 signing is not specified for backwards compatibility
awsSigv4SigningDefaultService = "s3"
// Default to urn:ietf:params:oauth:client-assertion-type:jwt-bearer for ClientAssertionType when not specified
defaultClientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
)

// DefaultTLSConfig defines standard TLS configurations based on the Config
Expand Down Expand Up @@ -281,6 +283,9 @@ type oauth2ClientCredentialsAuthPlugin struct {
AdditionalParameters map[string]string `json:"additional_parameters,omitempty"`
AWSKmsKey *awsKmsKeyConfig `json:"aws_kms,omitempty"`
AWSSigningPlugin *awsSigningAuthPlugin `json:"aws_signing,omitempty"`
ClientAssertionType string `json:"client_assertion_type"`
ClientAssertion string `json:"client_assertion"`
ClientAssertionPath string `json:"client_assertion_path"`

signingKey *keys.Config
signingKeyParsed interface{}
Expand Down Expand Up @@ -459,14 +464,30 @@ func (ap *oauth2ClientCredentialsAuthPlugin) NewClient(c Config) (*http.Client,
return nil, errors.New("token_url required to use https scheme")
}
if ap.GrantType == grantTypeClientCredentials {
if ap.AWSKmsKey != nil && (ap.ClientSecret != "" || ap.SigningKeyID != "") ||
(ap.ClientSecret != "" && ap.SigningKeyID != "") {
return nil, errors.New("can only use one of client_secret, signing_key or signing_kms_key for client_credentials")
clientCredentialExists := make(map[string]bool)
clientCredentialExists["client_secret"] = ap.ClientSecret != ""
clientCredentialExists["signing_key"] = ap.SigningKeyID != ""
clientCredentialExists["aws_kms"] = ap.AWSKmsKey != nil
clientCredentialExists["client_assertion"] = ap.ClientAssertion != ""
clientCredentialExists["client_assertion_path"] = ap.ClientAssertionPath != ""

var notEmptyVarCount int

for _, credentialSet := range clientCredentialExists {
if credentialSet {
notEmptyVarCount++
}
}

if notEmptyVarCount == 0 {
return nil, errors.New("please provide one of client_secret, signing_key, aws_kms, client_assertion, or client_assertion_path required")
}
if ap.SigningKeyID == "" && ap.AWSKmsKey == nil && (ap.ClientID == "" || ap.ClientSecret == "") {
return nil, errors.New("client_id and client_secret required")

if notEmptyVarCount > 1 {
return nil, errors.New("can only use one of client_secret, signing_key, aws_kms, client_assertion, or client_assertion_path")
}
if ap.AWSKmsKey != nil {

if clientCredentialExists["aws_kms"] {
if ap.AWSSigningPlugin == nil {
return nil, errors.New("aws_kms and aws_signing required")
}
Expand All @@ -475,6 +496,24 @@ func (ap *oauth2ClientCredentialsAuthPlugin) NewClient(c Config) (*http.Client,
if err != nil {
return nil, err
}
} else if clientCredentialExists["client_assertion"] {
if ap.ClientAssertionType == "" {
ap.ClientAssertionType = defaultClientAssertionType
}
if ap.ClientID == "" {
return nil, errors.New("client_id and client_assertion required")
}
} else if clientCredentialExists["client_assertion_path"] {
if ap.ClientAssertionType == "" {
ap.ClientAssertionType = defaultClientAssertionType
}
if ap.ClientID == "" {
return nil, errors.New("client_id and client_assertion_path required")
}
} else if clientCredentialExists["client_secret"] {
if ap.ClientID == "" {
return nil, errors.New("client_id and client_secret required")
}
}
}

Expand Down Expand Up @@ -502,12 +541,34 @@ func (ap *oauth2ClientCredentialsAuthPlugin) requestToken(ctx context.Context) (
if err != nil {
return nil, err
}
body.Add("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
body.Add("client_assertion_type", defaultClientAssertionType)
body.Add("client_assertion", *authJwt)

if ap.ClientID != "" {
body.Add("client_id", ap.ClientID)
}
} else if ap.ClientAssertion != "" {
if ap.ClientAssertionType == "" {
ap.ClientAssertionType = defaultClientAssertionType
}
if ap.ClientID != "" {
body.Add("client_id", ap.ClientID)
}
body.Add("client_assertion_type", ap.ClientAssertionType)
body.Add("client_assertion", ap.ClientAssertion)
} else if ap.ClientAssertionPath != "" {
if ap.ClientAssertionType == "" {
ap.ClientAssertionType = defaultClientAssertionType
}
bytes, err := os.ReadFile(ap.ClientAssertionPath)
if err != nil {
return nil, err
}
if ap.ClientID != "" {
body.Add("client_id", ap.ClientID)
}
body.Add("client_assertion_type", ap.ClientAssertionType)
body.Add("client_assertion", strings.TrimSpace(string(bytes)))
}
}

Expand Down
130 changes: 130 additions & 0 deletions plugins/rest/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,133 @@ func TestAssumeRoleWithUnsupportedSigningProvider(t *testing.T) {
t.Fatalf("expected error: %v but got: %v", expErrMsg, err)
}
}

func TestOauth2WithClientAssertion(t *testing.T) {
conf := `{
"name": "foo",
"url": "http://localhost",
"credentials": {
"oauth2": {
"grant_type": "client_credentials",
"token_url": "https://localhost",
"scopes": ["profile", "opa"],
"additional_claims": {
"aud": "some audience"
},
"client_id": "123",
"client_assertion": "abc123"
}
}
}`

client, err := New([]byte(conf), map[string]*keys.Config{})
if err != nil {
t.Fatalf("New() = %v", err)
}

if _, err := client.config.Credentials.OAuth2.NewClient(client.config); err != nil {
t.Fatalf("OAuth2.NewClient() = %q", err)
}

if client.config.Credentials.OAuth2.ClientAssertionType != defaultClientAssertionType {
t.Errorf("OAuth2.ClientAssertionType = %v, want = %v", client.config.Credentials.OAuth2.ClientAssertionType, defaultClientAssertionType)
}
}

func TestOauth2WithClientAssertionOverrideAssertionType(t *testing.T) {
conf := `{
"name": "foo",
"url": "http://localhost",
"credentials": {
"oauth2": {
"grant_type": "client_credentials",
"token_url": "https://localhost",
"scopes": ["profile", "opa"],
"additional_claims": {
"aud": "some audience"
},
"client_id": "123",
"client_assertion": "abc123",
"client_assertion_type": "urn:ietf:params:oauth:my-thing"
}
}
}`

client, err := New([]byte(conf), map[string]*keys.Config{})
if err != nil {
t.Fatalf("New() = %v", err)
}

if _, err := client.config.Credentials.OAuth2.NewClient(client.config); err != nil {
t.Fatalf("OAuth2.NewClient() = %q", err)
}

if client.config.Credentials.OAuth2.ClientAssertionType != "urn:ietf:params:oauth:my-thing" {
t.Errorf("OAuth2.ClientAssertionType = %v, want = %v", client.config.Credentials.OAuth2.ClientAssertionType, "urn:ietf:params:oauth:my-thing")
}
}

func TestOauth2WithClientAssertionPath(t *testing.T) {
conf := `{
"name": "foo",
"url": "http://localhost",
"credentials": {
"oauth2": {
"grant_type": "client_credentials",
"token_url": "https://localhost",
"scopes": ["profile", "opa"],
"additional_claims": {
"aud": "some audience"
},
"client_id": "123",
"client_assertion_path": "/var/run/secrets/azure/tokens/azure-identity-token"
}
}
}`

client, err := New([]byte(conf), map[string]*keys.Config{})
if err != nil {
t.Fatalf("New() = %v", err)
}

if _, err := client.config.Credentials.OAuth2.NewClient(client.config); err != nil {
t.Fatalf("OAuth2.NewClient() = %q", err)
}

if client.config.Credentials.OAuth2.ClientAssertionType != defaultClientAssertionType {
t.Errorf("OAuth2.ClientAssertionType = %v, want = %v", client.config.Credentials.OAuth2.ClientAssertionType, defaultClientAssertionType)
}
}

func TestOauth2WithClientAssertionPathOverrideAssertionType(t *testing.T) {
conf := `{
"name": "foo",
"url": "http://localhost",
"credentials": {
"oauth2": {
"grant_type": "client_credentials",
"token_url": "https://localhost",
"scopes": ["profile", "opa"],
"additional_claims": {
"aud": "some audience"
},
"client_id": "123",
"client_assertion_path": "/var/run/secrets/azure/tokens/azure-identity-token",
"client_assertion_type": "urn:ietf:params:oauth:my-thing"
}
}
}`

client, err := New([]byte(conf), map[string]*keys.Config{})
if err != nil {
t.Fatalf("New() = %v", err)
}

if _, err := client.config.Credentials.OAuth2.NewClient(client.config); err != nil {
t.Fatalf("OAuth2.NewClient() = %q", err)
}

if client.config.Credentials.OAuth2.ClientAssertionType != "urn:ietf:params:oauth:my-thing" {
t.Errorf("OAuth2.ClientAssertionType = %v, want = %v", client.config.Credentials.OAuth2.ClientAssertionType, "urn:ietf:params:oauth:my-thing")
}
}
32 changes: 32 additions & 0 deletions plugins/rest/rest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,38 @@ func TestNew(t *testing.T) {
}`,
wantErr: true,
},
{
name: "Oauth2CredsClientAssertionPath",
input: fmt.Sprintf(`{
"name": "foo",
"url": "http://localhost",
"credentials": {
"oauth2": {
"grant_type": %q,
"token_url": "https://localhost",
"client_id": "client_one",
"client_assertion_path": "/some/file",
"scopes": ["profile", "opa"]
}
}
}`, grantTypeClientCredentials),
},
{
name: "Oauth2CredsClientAssertion",
input: fmt.Sprintf(`{
"name": "foo",
"url": "http://localhost",
"credentials": {
"oauth2": {
"grant_type": %q,
"token_url": "https://localhost",
"client_id": "client_one",
"client_assertion": "assertive",
"scopes": ["profile", "opa"]
}
}
}`, grantTypeClientCredentials),
},
}

var results []Client
Expand Down