Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions pkg/serviceaccounts/oidc_identities.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@ type OIDCIdentityQuery struct {
Take int `uri:"take" url:"take"`
}

// OIDCIdentityClaimCondition is a condition a token claim must pass before Octopus exchanges the token for an access token.
// The token passes the condition when its claim matches any one of the values. Values support the same wildcards as the subject.
type OIDCIdentityClaimCondition struct {
Claim string `json:"Claim"`
Values []string `json:"Values"`
}

type OIDCIdentity struct {
Audience string `json:"Audience,omitempty"`
Issuer string `json:"Issuer"`
Name string `json:"Name"`
ServiceAccountID string `json:"ServiceAccountId"`
Subject string `json:"Subject"`

// ClaimConditions has no omitempty on purpose.
// On update, a nil slice is sent as null and Octopus keeps the existing conditions.
// An empty slice is sent as [] and Octopus removes them.
ClaimConditions []OIDCIdentityClaimCondition `json:"ClaimConditions"`
resources.Resource
}

Expand Down
42 changes: 42 additions & 0 deletions pkg/serviceaccounts/oidc_identities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,45 @@ func TestOIDCIdentity_MarshalJSON_IncludesAudienceWhenSet(t *testing.T) {

assert.Equal(t, "api://custom", result["Audience"])
}

func TestOIDCIdentity_MarshalJSON_SendsNullClaimConditionsWhenUnset(t *testing.T) {
identity := NewOIDCIdentity("ServiceAccounts-1", "name", "issuer", "subject")

data, err := json.Marshal(identity)
assert.NoError(t, err)

var result map[string]interface{}
err = json.Unmarshal(data, &result)
assert.NoError(t, err)

value, hasClaimConditions := result["ClaimConditions"]
assert.True(t, hasClaimConditions)
assert.Nil(t, value, "A nil slice must be sent as null so Octopus keeps the existing conditions")
}

func TestOIDCIdentity_MarshalJSON_SendsEmptyClaimConditionsToClearThem(t *testing.T) {
identity := NewOIDCIdentity("ServiceAccounts-1", "name", "issuer", "subject")
identity.ClaimConditions = []OIDCIdentityClaimCondition{}

data, err := json.Marshal(identity)
assert.NoError(t, err)

assert.Contains(t, string(data), `"ClaimConditions":[]`)
}

func TestOIDCIdentity_JSONRoundTrip_ClaimConditions(t *testing.T) {
identity := NewOIDCIdentity("ServiceAccounts-1", "name", "issuer", "subject")
identity.ClaimConditions = []OIDCIdentityClaimCondition{
{Claim: "repository_owner_id", Values: []string{"123456"}},
{Claim: "environment", Values: []string{"prod", "staging-*"}},
}

data, err := json.Marshal(identity)
assert.NoError(t, err)

var result OIDCIdentity
err = json.Unmarshal(data, &result)
assert.NoError(t, err)

assert.Equal(t, identity.ClaimConditions, result.ClaimConditions)
}
3 changes: 1 addition & 2 deletions test/e2e/project_trigger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ func CreateTestProjectTrigger(t *testing.T, client *client.Client, project *proj
start := time.Date(now.Year(), now.Month(), now.Day(), 9, 0, 0, 0, time.UTC)
// days := []filters.Weekday{filters.Sunday, filters.Monday}

action := actions.NewAutoDeployAction(createRandomBoolean())
// action := actions.NewDeployLatestReleaseAction(internal.GetRandomName(), createRandomBoolean(), []string{internal.GetRandomName()}, "")
action := actions.NewDeployLatestReleaseAction(environment.GetID(), createRandomBoolean(), []string{environment.GetID()}, "")
// action := actions.NewDeployNewReleaseAction(environment.GetID(), "", nil)
// filter := filters.NewDeploymentTargetFilter([]string{}, []string{}, []string{"MachineAvailableForDeployment"}, []string{})

Expand Down
Loading