Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
78fd8aa
APIGOV-31447 - support for okta group and policy
sbolosan Feb 23, 2026
9b14b37
APIGOV-31447 - update to agent details and okta provisioning
sbolosan Feb 24, 2026
bd395e1
APIGOV-31447 - update based on testing
sbolosan Mar 9, 2026
82567b4
APIGOV-31447 - update based on testing and refactor
sbolosan Mar 9, 2026
b701a43
APIGOV-31447 - update no testing sonar and logging fixes
sbolosan Mar 9, 2026
2aa7c50
APIGOV-31447 - update tests
sbolosan Mar 9, 2026
0a84f20
APIGOV-31447 - base commit with credential and application creation
sbolosan Mar 10, 2026
8ac76c9
APIGOV-31447 - group prov and deprov established
sbolosan Mar 10, 2026
25ceef8
APIGOV-31447 - tighten up prolicy and cilent update
sbolosan Mar 11, 2026
490d9d4
APIGOV-31447 - fail fast if group or policy is configured but not exist
sbolosan Mar 11, 2026
8a623f2
APIGOV-31447 - tie up some loose ends
sbolosan Mar 11, 2026
d1ba731
APIGOV-31447 - update hook failure and unregister
sbolosan Mar 12, 2026
bfbdf2a
Merge branch 'main' into APIGOV-31447
sbolosan Mar 12, 2026
5dda5bc
APIGOV-31447 - update sum
sbolosan Mar 12, 2026
b4a16e3
Merge branch 'main' into APIGOV-31447
sbolosan Mar 12, 2026
27ee420
APIGOV-31447 - updates to second round of mr bot findings
sbolosan Mar 12, 2026
b5b7501
APIGOV-31447 - add trace level log for all client or existing client …
sbolosan Mar 12, 2026
4b27618
APIGOV-31447 - low level logging fix for log process
sbolosan Mar 12, 2026
818b5f8
APIGOV-31447 - update based on JC code review
sbolosan Mar 12, 2026
ea62a0d
APIGOV-31447 - move out check up top
sbolosan Mar 12, 2026
13e1bcd
APIGOV-31447 - ran up against Mr.Bot proactive fixes
sbolosan Mar 12, 2026
4b03930
APIGOV-31447 - update on latest JC review comments
sbolosan Mar 13, 2026
7edf28b
Merge branch 'main' into APIGOV-31447
sbolosan Mar 13, 2026
2a5734f
APIGOV-31447 - first pass update based on comments
sbolosan Mar 13, 2026
de474b8
APIGOV-31447 - second batch of review comment updates
sbolosan Mar 13, 2026
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
25 changes: 25 additions & 0 deletions docs/discovery/provisioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,10 @@ type IDPConfig interface {
GetIDPName() string
// GetAuthConfig - to be used for authentication with IDP
GetAuthConfig() IDPAuthConfig
// GetOktaGroup - okta-specific group assignment configuration.
GetOktaGroup() string
// GetOktaPolicy - okta-specific authorization server policy name to look up.
GetOktaPolicy() string
// GetClientScopes - default list of scopes that are included in the client metadata request to IDP
GetClientScopes() string
// GetGrantType - default grant type to be used when creating the client. (default : "client_credentials")
Expand All @@ -635,6 +639,27 @@ AGENTFEATURES_IDP_AUTH_CLIENTSECRET_1="service-account-secret"
AGENTFEATURES_IDP_SCOPE_1="resource.READ resource.WRITE"
```

###### Okta provider configuration
To enrich Okta provisioning (group assignment and policy lookup), configure the Okta IDP with a group name and/or policy name.

Group assignment is configured via:

```
AGENTFEATURES_IDP_OKTA_GROUP_1="MyAppUsers"
```

Policy lookup is configured via:

```
AGENTFEATURES_IDP_OKTA_POLICY_1="MarketplacePolicy"
```

Notes:
- The SDK does not create groups or policies; they must already exist in Okta before the agent starts. If a configured group or policy cannot be found during provider initialization, `NewProvider` returns an error and the agent will fail to start.

Alternatively when registering the provider programmatically via `IDPConfiguration`, set the Okta group under `Okta.Group` and the policy name under `Okta.Policy`.


Alternatively, the agent implementation can choose to explicitly register the provider calling by using the `ProviderRegistry` interface.

```go
Expand Down
30 changes: 0 additions & 30 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down Expand Up @@ -467,10 +463,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -509,8 +501,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand All @@ -532,10 +522,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -584,16 +570,8 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2 h1:O1cMQHRfwNpDfDJerqRoE2oD+AFlyid87D40L/OkkJo=
golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8=
golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4 h1:bTLqdHv7xrGlFbvf5/TXNxy/iUwwdkjhqQTJDjW7aj0=
golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZrmR51cJDQxmJUHUOfRAaNyWBM+R+548=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand All @@ -605,10 +583,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down Expand Up @@ -664,10 +638,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
103 changes: 69 additions & 34 deletions pkg/apic/apiservicerevision.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,44 +73,22 @@ func (c *ServiceClient) buildAPIServiceRevision(serviceBody *ServiceBody) *manag
func (c *ServiceClient) processRevision(serviceBody *ServiceBody) error {
log := c.logger
logProcess := "Creating"

apiServiceRevisions := make([]*management.APIServiceRevision, 0)
if serviceBody.serviceContext.serviceAction == updateAPI {
logProcess = "Updating"
}

// get current revisions
revisions, totalCount, err := c.getRevisions("metadata.references.id==" + serviceBody.serviceContext.serviceID)
if err != nil {
return err
}
serviceBody.serviceContext.revisionCount = totalCount
apiServiceRevisions = revisions
apiServiceRevisions, err := c.getRevisionsIfUpdating(serviceBody)
if err != nil {
return err
}

// check if a revision with the same hash was already published
if revName, found := serviceBody.specHashes[serviceBody.specHash]; found {
name := revName.(string)

// check to see if the tags have changed from the latest
for _, apiServiceRevision := range apiServiceRevisions {
if apiServiceRevision.Name == name {
updatedTags := c.getUpdatedTagKeys(serviceBody.Tags, apiServiceRevision.Tags)
if len(updatedTags) > 0 {
updatedRevision := c.buildAPIServiceRevision(serviceBody)
updatedRevision.Name = apiServiceRevision.Name
updatedRevision.Metadata.Scope = v1.MetadataScope{
Kind: management.EnvironmentGVK().Kind,
Name: c.cfg.GetEnvironmentName(),
}
_, err := c.UpdateResourceInstance(updatedRevision)
if err != nil {
return err
}
}
serviceBody.serviceContext.revisionName = name
return nil
}
}
// check if a revision with the same hash was already published and update tags if needed
found, err := c.checkAndUpdateExistingRevision(serviceBody, apiServiceRevisions)
if err != nil {
return err
}
if found {
return nil
}

log.
Expand All @@ -120,6 +98,11 @@ func (c *ServiceClient) processRevision(serviceBody *ServiceBody) error {
WithField("environment", c.cfg.GetEnvironmentName()).
Info("process revision")

return c.createOrUpdateRevision(serviceBody)
}

// createOrUpdateRevision encapsulates CreateOrUpdateResource and rollback handling
func (c *ServiceClient) createOrUpdateRevision(serviceBody *ServiceBody) error {
rev, err := c.CreateOrUpdateResource(c.buildAPIServiceRevision(serviceBody))
if err != nil {
if serviceBody.serviceContext.serviceAction == addAPI {
Expand All @@ -132,7 +115,6 @@ func (c *ServiceClient) processRevision(serviceBody *ServiceBody) error {
}

serviceBody.serviceContext.revisionName = rev.Name

return nil
}

Expand Down Expand Up @@ -166,6 +148,59 @@ func (c *ServiceClient) getRevisions(queryString string) ([]*management.APIServi
return apiServiceRevisions, count, nil
}

// getRevisionsIfUpdating returns revisions when the service action is an update
func (c *ServiceClient) getRevisionsIfUpdating(serviceBody *ServiceBody) ([]*management.APIServiceRevision, error) {
apiServiceRevisions := make([]*management.APIServiceRevision, 0)
if serviceBody.serviceContext.serviceAction == updateAPI {
// get current revisions
revisions, totalCount, err := c.getRevisions("metadata.references.id==" + serviceBody.serviceContext.serviceID)
if err != nil {
return nil, err
}
serviceBody.serviceContext.revisionCount = totalCount
apiServiceRevisions = revisions
}
return apiServiceRevisions, nil
}

// checkAndUpdateExistingRevision checks if a revision with the same hash exists and updates tags if needed
func (c *ServiceClient) checkAndUpdateExistingRevision(serviceBody *ServiceBody, apiServiceRevisions []*management.APIServiceRevision) (bool, error) {
revName, found := serviceBody.specHashes[serviceBody.specHash]
if !found {
return false, nil
}

name := revName.(string)

// check to see if the tags have changed from the latest
for _, apiServiceRevision := range apiServiceRevisions {
if apiServiceRevision.Name != name {
continue
}

serviceBody.serviceContext.revisionName = name

updatedTags := c.getUpdatedTagKeys(serviceBody.Tags, apiServiceRevision.Tags)
if len(updatedTags) == 0 {
return true, nil
}

updatedRevision := c.buildAPIServiceRevision(serviceBody)
updatedRevision.Name = apiServiceRevision.Name
updatedRevision.Metadata.Scope = v1.MetadataScope{
Kind: management.EnvironmentGVK().Kind,
Name: c.cfg.GetEnvironmentName(),
}
_, err := c.UpdateResourceInstance(updatedRevision)
if err != nil {
return false, err
}

return true, nil
}
Comment thread
sbolosan marked this conversation as resolved.
return false, nil
}

// verify last revision tags against the serviceBody tags that are coming in to see if they are equal or not. If they are not, return an empty[]. If they are
// different, return the updated tags
func (c *ServiceClient) getUpdatedTagKeys(serviceBodyTags map[string]interface{}, revisionTags []string) []string {
Expand Down
Loading
Loading