diff --git a/.changeset/canton-okta-env-bindings.md b/.changeset/canton-okta-env-bindings.md new file mode 100644 index 000000000..9e6a91027 --- /dev/null +++ b/.changeset/canton-okta-env-bindings.md @@ -0,0 +1,5 @@ +--- +"chainlink-deployments-framework": patch +--- + +Accept `ONCHAIN_CANTON_OKTA_*` environment variables as legacy aliases for Canton OAuth config and infer `client_credentials` when OAuth secrets are set without `ONCHAIN_CANTON_AUTH_STRATEGY`. diff --git a/engine/cld/chains/chains.go b/engine/cld/chains/chains.go index 99055e816..c9d3e594a 100644 --- a/engine/cld/chains/chains.go +++ b/engine/cld/chains/chains.go @@ -786,14 +786,31 @@ func (l *chainLoaderCanton) Load(ctx context.Context, selector uint64) (fchain.B return c, nil } +// cantonEffectiveAuthStrategy resolves the auth strategy from explicit config or available credentials. +// When auth_strategy is unset, OAuth client credentials are inferred if auth_url, client_id, and +// client_secret are all present (e.g. ONCHAIN_CANTON_OKTA_* from chainlink-deployments CI secrets). +func cantonEffectiveAuthStrategy(c cfgenv.CantonConfig) string { + if c.AuthStrategy != "" { + return c.AuthStrategy + } + if c.AuthURL != "" && c.ClientID != "" && c.ClientSecret != "" { + return cfgenv.CantonAuthStrategyClientCredentials + } + if c.AuthURL != "" && c.ClientID != "" { + return cfgenv.CantonAuthStrategyAuthorizationCode + } + + return cfgenv.CantonAuthStrategyStatic +} + // cantonAuthConfigured returns true if Canton auth is configured for at least one strategy. func cantonAuthConfigured(c cfgenv.CantonConfig) bool { - switch c.AuthStrategy { + switch cantonEffectiveAuthStrategy(c) { case cfgenv.CantonAuthStrategyClientCredentials: return c.AuthURL != "" && c.ClientID != "" && c.ClientSecret != "" case cfgenv.CantonAuthStrategyAuthorizationCode: return c.AuthURL != "" && c.ClientID != "" - case "", cfgenv.CantonAuthStrategyStatic: + case cfgenv.CantonAuthStrategyStatic: return c.JWTToken != "" default: return false @@ -803,7 +820,7 @@ func cantonAuthConfigured(c cfgenv.CantonConfig) bool { // cantonAuthProvider builds a Canton auth Provider from config. func (l *chainLoaderCanton) cantonAuthProvider(ctx context.Context, selector uint64, insecureTransport bool) (cantonauth.Provider, error) { c := l.cfg.Canton - switch c.AuthStrategy { + switch cantonEffectiveAuthStrategy(c) { case cfgenv.CantonAuthStrategyClientCredentials: provider, err := cantonclientcreds.NewDiscoveryProvider(ctx, c.AuthURL, c.ClientID, c.ClientSecret) if err != nil { diff --git a/engine/cld/chains/chains_test.go b/engine/cld/chains/chains_test.go index 47cfab69f..8a1001230 100644 --- a/engine/cld/chains/chains_test.go +++ b/engine/cld/chains/chains_test.go @@ -1399,6 +1399,11 @@ func Test_cantonAuthConfigured(t *testing.T) { config: cfgenv.CantonConfig{AuthStrategy: cfgenv.CantonAuthStrategyClientCredentials, AuthURL: "https://auth.example.com", ClientID: "id", ClientSecret: "secret"}, want: true, }, + { + name: "client credentials inferred without strategy", + config: cfgenv.CantonConfig{AuthURL: "https://auth.example.com", ClientID: "id", ClientSecret: "secret"}, + want: true, + }, { name: "client credentials missing secret", config: cfgenv.CantonConfig{AuthStrategy: cfgenv.CantonAuthStrategyClientCredentials, AuthURL: "https://auth.example.com", ClientID: "id"}, diff --git a/engine/cld/config/env/config.go b/engine/cld/config/env/config.go index 046b490b5..88c04b584 100644 --- a/engine/cld/config/env/config.go +++ b/engine/cld/config/env/config.go @@ -283,9 +283,9 @@ var ( "onchain.ton.wallet_version": {"ONCHAIN_TON_WALLET_VERSION", "TON_WALLET_VERSION"}, "onchain.canton.auth_strategy": {"ONCHAIN_CANTON_AUTH_STRATEGY"}, "onchain.canton.jwt_token": {"ONCHAIN_CANTON_JWT_TOKEN"}, - "onchain.canton.auth_url": {"ONCHAIN_CANTON_AUTH_URL"}, - "onchain.canton.client_id": {"ONCHAIN_CANTON_CLIENT_ID"}, - "onchain.canton.client_secret": {"ONCHAIN_CANTON_CLIENT_SECRET"}, + "onchain.canton.auth_url": {"ONCHAIN_CANTON_AUTH_URL", "ONCHAIN_CANTON_OKTA_AUTHORIZER"}, + "onchain.canton.client_id": {"ONCHAIN_CANTON_CLIENT_ID", "ONCHAIN_CANTON_OKTA_CLIENT_ID"}, + "onchain.canton.client_secret": {"ONCHAIN_CANTON_CLIENT_SECRET", "ONCHAIN_CANTON_OKTA_CLIENT_SECRET"}, "offchain.job_distributor.auth.cognito_app_client_id": {"OFFCHAIN_JD_AUTH_COGNITO_APP_CLIENT_ID", "JD_AUTH_COGNITO_APP_CLIENT_ID"}, "offchain.job_distributor.auth.cognito_app_client_secret": {"OFFCHAIN_JD_AUTH_COGNITO_APP_CLIENT_SECRET", "JD_AUTH_COGNITO_APP_CLIENT_SECRET"}, "offchain.job_distributor.auth.aws_region": {"OFFCHAIN_JD_AUTH_AWS_REGION", "JD_AUTH_AWS_REGION"}, diff --git a/engine/cld/config/env/config_test.go b/engine/cld/config/env/config_test.go index d94135ead..32d0b75f2 100644 --- a/engine/cld/config/env/config_test.go +++ b/engine/cld/config/env/config_test.go @@ -354,6 +354,21 @@ func Test_LoadEnv_Legacy(t *testing.T) { //nolint:paralleltest // see comment in assert.Equal(t, envCfg, got) } +func Test_LoadEnv_CantonOktaLegacyBindings(t *testing.T) { //nolint:paralleltest // see comment in setupEnvVars + t.Setenv("ONCHAIN_CANTON_OKTA_AUTHORIZER", "https://smartcontract.okta.com/oauth2/ausspv7t7qurBgkou5d7") + t.Setenv("ONCHAIN_CANTON_OKTA_CLIENT_ID", "0oat4r1zfzm83nL2m5d7") + t.Setenv("ONCHAIN_CANTON_OKTA_CLIENT_SECRET", "test-client-secret") + + got, err := LoadEnv() + require.NoError(t, err) + + assert.Equal(t, CantonConfig{ + AuthURL: "https://smartcontract.okta.com/oauth2/ausspv7t7qurBgkou5d7", + ClientID: "0oat4r1zfzm83nL2m5d7", + ClientSecret: "test-client-secret", + }, got.Onchain.Canton) +} + func Test_LoadEnv_BindsCREFromEnv(t *testing.T) { //nolint:paralleltest // see comment in setupEnvVars t.Setenv("CRE_API_KEY", "api-key-1") t.Setenv("CRE_TENANT_ID", "tenant-1") diff --git a/go.mod b/go.mod index e2625ea0e..1f05ba44b 100644 --- a/go.mod +++ b/go.mod @@ -33,20 +33,20 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.101 github.com/smartcontractkit/chainlink-aptos v0.0.0-20260428085939-5c70de12dbfc - github.com/smartcontractkit/chainlink-canton v0.0.0-20260602133237-99f834640c9d - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260512180815-d7a89b0a5784 + github.com/smartcontractkit/chainlink-canton v0.0.0-20260609155219-dcbe77d4a320 + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260608180601-efa81bfdfda9 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260129103204-4c8453dd8139 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260129103204-4c8453dd8139 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/op-catalog v0.1.0 - github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.4 + github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.5 github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 github.com/smartcontractkit/chainlink-ton v1.0.5-0.20260514223130-48bc90aca745 github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20251014143056-a0c6328c91e9 github.com/smartcontractkit/freeport v0.1.3-0.20250828155247-add56fa28aad github.com/smartcontractkit/go-daml v0.0.0-20260604143752-c6f6567940ba github.com/smartcontractkit/libocr v0.0.0-20260304194147-a03701e2c02e - github.com/smartcontractkit/mcms v0.47.0 + github.com/smartcontractkit/mcms v0.47.1-0.20260609163952-0b2bf692ba6a github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 @@ -145,7 +145,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect - github.com/aws/smithy-go v1.27.0 // indirect + github.com/aws/smithy-go v1.27.1 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -194,7 +194,7 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.2 // indirect + github.com/go-playground/validator/v10 v10.30.3 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect diff --git a/go.sum b/go.sum index a798582c2..c3de32f30 100644 --- a/go.sum +++ b/go.sum @@ -76,6 +76,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8 github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= github.com/aws/smithy-go v1.27.0 h1:ZoFioDKJxkSIW2otF9T0aPtNlUwhdVCcuZh/rzH9Hus= github.com/aws/smithy-go v1.27.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/smithy-go v1.27.1 h1:4T340VFndXtADGF52gYa1POyL7s9E4Z1OeZ1hCscIw8= +github.com/aws/smithy-go v1.27.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -297,6 +299,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ= github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc= +github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8= +github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc= github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk= github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= @@ -673,8 +677,12 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260428085939-5c70de12dbfc h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260428085939-5c70de12dbfc/go.mod h1:zfE2R7887kiwXkGTHKPe5NBgwhFwIC3pnA2uAxrbvig= github.com/smartcontractkit/chainlink-canton v0.0.0-20260602133237-99f834640c9d h1:aBQYdlGQvqftkcUo0GIgtaLDs/84FQzBYpF4tZUfPA0= github.com/smartcontractkit/chainlink-canton v0.0.0-20260602133237-99f834640c9d/go.mod h1:/oTkN9bVrQ1ROUNtIJJSNdffl3NReClq+qINNkGAwlY= +github.com/smartcontractkit/chainlink-canton v0.0.0-20260609155219-dcbe77d4a320 h1:ix4tCtSTB7S2XGll+uqnhrqAQ+2iW/Zk/vnPjBMYRB0= +github.com/smartcontractkit/chainlink-canton v0.0.0-20260609155219-dcbe77d4a320/go.mod h1:WKmNUX4oy8IvB66ukudrE99uaXjlZ7WghCDwHOTyB1c= github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260512180815-d7a89b0a5784 h1:s0rW7GaIKf9m+kfv0dFJPdSbHaMqQiv3xamQP2RVWNE= github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260512180815-d7a89b0a5784/go.mod h1:0dcvbCc+HRK+nIweRSHu3FjkNTV9gi+irBIB3mUUe68= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260608180601-efa81bfdfda9 h1:rLU5tQ/1BaQOjnYj9WWNlbqXCqd61oqasOXJ7upaKaM= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260608180601-efa81bfdfda9/go.mod h1:TfYlPkIj2wa35qqWLrk5//HkLoee5jzokxZ7PhK0tgk= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260129103204-4c8453dd8139 h1:jkChf04hhdiMBApbb+lLDxHMY62Md6UeM7v++GSw3K8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260129103204-4c8453dd8139/go.mod h1:wuhagkM/lU0GbV2YcrROOH0GlsfXJYwm6qmpa4CK70w= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260129103204-4c8453dd8139 h1:tw3K4UkH5XfW5SoyYkvAlbzrccoGSLdz/XkxD6nyGC8= @@ -697,6 +705,8 @@ github.com/smartcontractkit/chainlink-sui v0.0.0-20260527160341-aa3adc0abf67 h1: github.com/smartcontractkit/chainlink-sui v0.0.0-20260527160341-aa3adc0abf67/go.mod h1:k1HSbHyPaQWPOj6lXDIAe04EuwbC5ge1nK+cpG2E8hE= github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.4 h1:8M+2pA0qx9rXaxmpKouUHj983vQCGzztHkG0XjE5Eew= github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.4/go.mod h1:nyOjn4ADJGqRMe3+4ZXSV+J/7nWb1H2Vx8Qk57eLRYA= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.5 h1:EiQx0LCPzxlfO9piSPeMCVSZAnp/BxAsPIGh/jBal18= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.5/go.mod h1:nyOjn4ADJGqRMe3+4ZXSV+J/7nWb1H2Vx8Qk57eLRYA= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 h1:RwZXxdIAOyjp6cwc9Quxgr38k8r7ACz+Lxh9o/A6oH0= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5/go.mod h1:kHYJnZUqiPF7/xN5273prV+srrLJkS77GbBXHLKQpx0= github.com/smartcontractkit/chainlink-ton v1.0.5-0.20260514223130-48bc90aca745 h1:eieKLvYuzwBPh/FdbUS1gnIanI86zgWby1L10o90g4o= @@ -715,6 +725,8 @@ github.com/smartcontractkit/libocr v0.0.0-20260304194147-a03701e2c02e h1:poXTj5c github.com/smartcontractkit/libocr v0.0.0-20260304194147-a03701e2c02e/go.mod h1:PLdNK6GlqfxIWXzziPkU7dCAVlVFeYkyyW7AQY0R+4Q= github.com/smartcontractkit/mcms v0.47.0 h1:MiwpQZwZUwdRJ1HGEO3EkLHj5+g95P84HXcHeY9gMFw= github.com/smartcontractkit/mcms v0.47.0/go.mod h1:PBWZPScZKC87jDMxcd5WvKDdlvTgA7k8qHkCeNkGBN8= +github.com/smartcontractkit/mcms v0.47.1-0.20260609163952-0b2bf692ba6a h1:Md5YPRT2oIgSD6U/gvy3BkB3hWXufu+eWIA+0ZFkngc= +github.com/smartcontractkit/mcms v0.47.1-0.20260609163952-0b2bf692ba6a/go.mod h1:7ZPOnN9CeoiiZkGQSPsyk23X+XFEtxQYpIx7kKy2ZP0= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=