From 01a70062a3b2aed8351229d43d94e520ec3c1e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Budzy=C5=84ski?= Date: Thu, 19 Sep 2024 10:26:08 +0200 Subject: [PATCH] added remaining integration tests --- pkg/sdk/secrets_def.go | 25 +- pkg/sdk/secrets_gen.go | 9 +- .../testint/secrets_gen_integration_test.go | 565 +++++++++++++++--- 3 files changed, 505 insertions(+), 94 deletions(-) diff --git a/pkg/sdk/secrets_def.go b/pkg/sdk/secrets_def.go index 9ecfb0bf465..ddd1fa95fd4 100644 --- a/pkg/sdk/secrets_def.go +++ b/pkg/sdk/secrets_def.go @@ -15,7 +15,7 @@ var secretDbRow = g.DbStruct("secretDBRow"). Field("owner", "string"). Field("comment", "sql.NullString"). Field("secret_type", "string"). - Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("oauth_scopes", "sql.NullString"). Field("owner_role_type", "string") var secret = g.PlainStruct("Secret"). @@ -40,7 +40,7 @@ var secretDetailsDbRow = g.DbStruct("secretDetailsDBRow"). Field("username", "sql.NullString"). Time("oauth_access_token_expiry_time"). Time("oauth_refresh_token_expiry_time"). - Field("oauth_scopes", "sql.NullString"). // its a list tho + Field("oauth_scopes", "sql.NullString"). Field("integration_name", "sql.NullString") var secretDetails = g.PlainStruct("SecretDetails"). @@ -52,9 +52,9 @@ var secretDetails = g.PlainStruct("SecretDetails"). Field("Comment", "sql.NullString"). Field("SecretType", "string"). Field("Username", "sql.NullString"). - Time("OauthAccessTokenExpiryTime"). - Time("OauthRefreshTokenExpiryTime"). - Field("OauthScopes", "sql.NullString"). // its a list tho + Field("OauthAccessTokenExpiryTime", "*time.Time"). + Field("OauthRefreshTokenExpiryTime", "*time.Time"). + Field("OauthScopes", "sql.NullString"). Field("IntegrationName", "sql.NullString") var secretSet = g.NewQueryStruct("SecretSet"). @@ -87,9 +87,8 @@ var secretSet = g.NewQueryStruct("SecretSet"). ). WithValidation(g.ExactlyOneValueSet, "SetForOAuthClientCredentialsFlow", "SetForOAuthAuthorizationFlow", "SetForBasicAuthentication", "SetForGenericString") -// TODO: UNSET doest work, need to use "SET COMMENT = NULL" +// UNSET doest work, need to use "SET COMMENT = NULL" var secretUnset = g.NewQueryStruct("SecretUnset"). - //OptionalSQL("UNSET COMMENT") PredefinedQueryStructField("Comment", "*bool", g.KeywordOptions().SQL("SET COMMENT = NULL")) var SecretsDef = g.NewInterface( @@ -199,18 +198,6 @@ var SecretsDef = g.NewInterface( "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", secretDetailsDbRow, secretDetails, - - /* - g.DescriptionMappingKindSlice, - "https://docs.snowflake.com/en/sql-reference/sql/desc-secret", - g.DbStruct("secretDetailsRow"). - Field("property", "string"). - Field("value", "sql.NullString"), - g.PlainStruct("SecretDetails"). - Field("Property", "string"). - Field("Value", "string"), - */ - g.NewQueryStruct("DescribeSecret"). Describe(). SQL("SECRET"). diff --git a/pkg/sdk/secrets_gen.go b/pkg/sdk/secrets_gen.go index 6ff0313c1e3..b90ac53ea30 100644 --- a/pkg/sdk/secrets_gen.go +++ b/pkg/sdk/secrets_gen.go @@ -3,6 +3,7 @@ package sdk import ( "context" "database/sql" + "time" ) type Secrets interface { @@ -159,8 +160,8 @@ type secretDetailsDBRow struct { Comment sql.NullString `db:"comment"` SecretType string `db:"secret_type"` Username sql.NullString `db:"username"` - OauthAccessTokenExpiryTime sql.NullString `db:"oauth_access_token_expiry_time"` - OauthRefreshTokenExpiryTime sql.NullString `db:"oauth_refresh_token_expiry_time"` + OauthAccessTokenExpiryTime *time.Time `db:"oauth_access_token_expiry_time"` + OauthRefreshTokenExpiryTime *time.Time `db:"oauth_refresh_token_expiry_time"` OauthScopes sql.NullString `db:"oauth_scopes"` IntegrationName sql.NullString `db:"integration_name"` } @@ -173,8 +174,8 @@ type SecretDetails struct { Comment sql.NullString SecretType string Username sql.NullString - OauthAccessTokenExpiryTime sql.NullString - OauthRefreshTokenExpiryTime sql.NullString + OauthAccessTokenExpiryTime *time.Time + OauthRefreshTokenExpiryTime *time.Time OauthScopes sql.NullString IntegrationName sql.NullString } diff --git a/pkg/sdk/testint/secrets_gen_integration_test.go b/pkg/sdk/testint/secrets_gen_integration_test.go index d86270636e1..ce1070e6542 100644 --- a/pkg/sdk/testint/secrets_gen_integration_test.go +++ b/pkg/sdk/testint/secrets_gen_integration_test.go @@ -1,6 +1,7 @@ package testint import ( + "database/sql" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/stretchr/testify/assert" @@ -9,11 +10,27 @@ import ( "time" ) +const Day = 24 * time.Hour + func TestInt_Secrets(t *testing.T) { client := testClient(t) ctx := testContext(t) + integrationId := testClientHelper().Ids.RandomAccountObjectIdentifier() + refreshTokenExpiryTime := time.Now().Add(Day).Format(time.DateOnly) + + stringDateToSnowflakeTimeFormat := func(inputLayout, date string) *time.Time { + parsedTime, err := time.Parse(inputLayout, date) + require.NoError(t, err) + + loc, err := time.LoadLocation("America/Los_Angeles") + require.NoError(t, err) + + adjustedTime := parsedTime.In(loc) + return &adjustedTime + } + cleanupIntegration := func(t *testing.T, integrationId sdk.AccountObjectIdentifier) func() { return func() { err := client.SecurityIntegrations.Drop(ctx, sdk.NewDropSecurityIntegrationRequest(integrationId).WithIfExists(true)) @@ -21,31 +38,22 @@ func TestInt_Secrets(t *testing.T) { } } - integrationRequest := sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). - WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}) - err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow(ctx, integrationRequest) + err := client.SecurityIntegrations.CreateApiAuthenticationWithClientCredentialsFlow( + ctx, + sdk.NewCreateApiAuthenticationWithClientCredentialsFlowSecurityIntegrationRequest(integrationId, true, "foo", "foo"). + WithOauthAllowedScopes([]sdk.AllowedScope{{"foo"}, {"bar"}}), + ) require.NoError(t, err) t.Cleanup(cleanupIntegration(t, integrationId)) - cleanupSecret := func(id sdk.SchemaObjectIdentifier) func() { + cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() return func() { err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) require.NoError(t, err) } } - assertSecret := func(t *testing.T, s *sdk.Secret, expectedId sdk.SchemaObjectIdentifier, expectedSecretType, expectedComment string) { - t.Helper() - assert.Equal(t, expectedId.Name(), s.Name) - assert.Equal(t, expectedSecretType, s.SecretType) - assert.Equal(t, expectedComment, s.Comment) - assert.NotEmpty(t, s.CreatedOn) - assert.NotEmpty(t, s.DatabaseName) - assert.NotEmpty(t, s.SchemaName) - assert.NotEmpty(t, s.OwnerRoleType) - assert.NotEmpty(t, s.Owner) - } - createSecretWithOAuthClientCredentialsFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, scopes []sdk.SecurityIntegrationScope, with func(*sdk.CreateWithOAuthClientCredentialsFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() @@ -55,7 +63,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithOAuthClientCredentialsFlow(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + t.Cleanup(cleanupSecret(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -63,7 +71,7 @@ func TestInt_Secrets(t *testing.T) { return secret, id } - createSecretWithOAuthAuthorizationCodeFlow := func(t *testing.T, refreshToken, refreshTokenExpiryTime string, integrationId sdk.AccountObjectIdentifier, with func(*sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + createSecretWithOAuthAuthorizationCodeFlow := func(t *testing.T, integrationId sdk.AccountObjectIdentifier, refreshToken, refreshTokenExpiryTime string, with func(*sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithOAuthAuthorizationCodeFlowSecretRequest(id, refreshToken, refreshTokenExpiryTime, integrationId) @@ -72,7 +80,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithOAuthAuthorizationCodeFlow(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + t.Cleanup(cleanupSecret(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -80,7 +88,7 @@ func TestInt_Secrets(t *testing.T) { return secret, id } - createSecretWithBasicAuthorization := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + createSecretWithBasicAuthentication := func(t *testing.T, username, password string, with func(*sdk.CreateWithBasicAuthenticationSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { t.Helper() id := testClientHelper().Ids.RandomSchemaObjectIdentifier() request := sdk.NewCreateWithBasicAuthenticationSecretRequest(id, username, password) @@ -89,7 +97,7 @@ func TestInt_Secrets(t *testing.T) { } err := client.Secrets.CreateWithBasicAuthentication(ctx, request) require.NoError(t, err) - t.Cleanup(cleanupSecret(id)) + t.Cleanup(cleanupSecret(t, id)) secret, err := client.Secrets.ShowByID(ctx, id) require.NoError(t, err) @@ -97,13 +105,42 @@ func TestInt_Secrets(t *testing.T) { return secret, id } + createSecretWithGenericString := func(t *testing.T, secretString string, with func(options *sdk.CreateWithGenericStringSecretRequest)) (*sdk.Secret, sdk.SchemaObjectIdentifier) { + t.Helper() + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) + if with != nil { + with(request) + } + err := client.Secrets.CreateWithGenericString(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(t, id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret, id + } + + assertSecret := func(t *testing.T, s *sdk.Secret, expectedId sdk.SchemaObjectIdentifier, expectedSecretType, expectedComment string) { + t.Helper() + assert.Equal(t, expectedId.Name(), s.Name) + assert.Equal(t, expectedSecretType, s.SecretType) + assert.Equal(t, expectedComment, s.Comment) + assert.NotEmpty(t, s.CreatedOn) + assert.NotEmpty(t, s.DatabaseName) + assert.NotEmpty(t, s.SchemaName) + assert.NotEmpty(t, s.OwnerRoleType) + assert.NotEmpty(t, s.Owner) + } + type secretDetails struct { Name string Comment string SecretType string Username string - OauthAccessTokenExpiryTime time.Time - OauthRefreshTokenExpiryTime time.Time + OauthAccessTokenExpiryTime *time.Time + OauthRefreshTokenExpiryTime *time.Time OauthScopes string IntegrationName string } @@ -113,14 +150,15 @@ func TestInt_Secrets(t *testing.T) { assert.Equal(t, expected.Comment, actual.Comment.String) assert.Equal(t, expected.SecretType, actual.SecretType) assert.Equal(t, expected.Username, actual.Username.String) - assert.Equal(t, expected.OauthAccessTokenExpiryTime.String(), actual.OauthAccessTokenExpiryTime.String) - assert.Equal(t, expected.OauthRefreshTokenExpiryTime.String(), actual.OauthRefreshTokenExpiryTime.String) + assert.Equal(t, expected.OauthAccessTokenExpiryTime, actual.OauthAccessTokenExpiryTime) + assert.Equal(t, expected.OauthRefreshTokenExpiryTime, actual.OauthRefreshTokenExpiryTime) assert.Equal(t, expected.OauthScopes, actual.OauthScopes.String) assert.Equal(t, expected.IntegrationName, actual.IntegrationName.String) } - t.Run("Create secret with OAuth Client Credentials Flow", func(t *testing.T) { + t.Run("Create: secretWithOAuthClientCredentialsFlow", func(t *testing.T) { scopes := []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}} + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, scopes, func(req *sdk.CreateWithOAuthClientCredentialsFlowSecretRequest) { req.WithComment("a"). WithIfNotExists(true) @@ -139,24 +177,39 @@ func TestInt_Secrets(t *testing.T) { assertSecret(t, secret, id, "OAUTH2", "a") }) - // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not - t.Run("CreateSecretWithOAuthClientCredentialsFlow: No Scopes Specified", func(t *testing.T) { + // It is possible to create secret without specifying both refresh token properties and scopes + // Scopes are not being inherited from the security_integration what is tested further + t.Run("Create: secretWithOAuth - minimal, without token and scopes", func(t *testing.T) { secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) - details, err := client.Secrets.Describe(ctx, id) require.NoError(t, err) assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "OAUTH2", - IntegrationName: integrationId.Name(), + Name: id.Name(), + SecretType: "OAUTH2", + OauthScopes: "", + OauthAccessTokenExpiryTime: nil, + OauthRefreshTokenExpiryTime: nil, + IntegrationName: integrationId.Name(), }) assertSecret(t, secret, id, "OAUTH2", "") }) - t.Run("CreateWithOAuthAuthorizationCodeFlow", func(t *testing.T) { - secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, "foo", "2024-09-20", integrationId, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { + // regarding the https://docs.snowflake.com/en/sql-reference/sql/create-secret secret should inherit security_integration scopes, but it does not do so + t.Run("Create: SecretWithOAuthClientCredentialsFlow - No Scopes Specified", func(t *testing.T) { + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{}, nil) + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + securityIntegrationProperties, _ := client.SecurityIntegrations.Describe(ctx, integrationId) + assert.Contains(t, securityIntegrationProperties, sdk.SecurityIntegrationProperty{Name: "OAUTH_ALLOWED_SCOPES", Type: "List", Value: "[foo, bar]", Default: "[]"}) + + assert.NotEqual(t, details.OauthScopes, securityIntegrationProperties) + }) + + t.Run("Create: SecretWithOAuthAuthorizationCodeFlow", func(t *testing.T) { + secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { req.WithComment("a"). WithIfNotExists(true) }) @@ -168,39 +221,17 @@ func TestInt_Secrets(t *testing.T) { Name: id.Name(), SecretType: "OAUTH2", Comment: "a", - OauthRefreshTokenExpiryTime: time.Time{}, //"2024-09-20", + OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, refreshTokenExpiryTime), IntegrationName: integrationId.Name(), }) - assertSecret(t, secret, id, "OAUTH2", "") + assertSecret(t, secret, id, "OAUTH2", "a") }) - /* - //require.EqualError(t, err, "Invalid data/time format string") - t.Run("CreateWithOAuthAuthorizationCodeFlow: Invalid date/time format string", func(t *testing.T) { - secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, func(req *sdk.CreateWithOAuthAuthorizationCodeFlowSecretRequest) { - req.WithComment("a"). - WithIfNotExists(true) - }) - - details, err := client.Secrets.Describe(ctx, id) - require.NoError(t, err) - - assertSecretDetails(details, secretDetails{ - Name: id.Name(), - SecretType: "OAUTH2", - OauthAccessTokenExpiryTime: "foo", - OauthRefreshTokenExpiryTime: "foo", - IntegrationName: integrationId.Name(), - }) - - assertSecret(t, secret, id, "OAUTH2", "") - }) - */ - - t.Run("CreateWithBasicAuthentication", func(t *testing.T) { + t.Run("Create: WithBasicAuthentication", func(t *testing.T) { comment := random.Comment() - secret, id := createSecretWithBasicAuthorization(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { + + secret, id := createSecretWithBasicAuthentication(t, "foo", "foo", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { req.WithComment(comment). WithIfNotExists(true) }) @@ -217,9 +248,9 @@ func TestInt_Secrets(t *testing.T) { assertSecret(t, secret, id, "PASSWORD", comment) }) - t.Run("CreateWithBasicAuthentication: Empty Username and Password", func(t *testing.T) { + t.Run("Create: WithBasicAuthentication - Empty Username and Password", func(t *testing.T) { comment := random.Comment() - secret, id := createSecretWithBasicAuthorization(t, "", "", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { + secret, id := createSecretWithBasicAuthentication(t, "", "", func(req *sdk.CreateWithBasicAuthenticationSecretRequest) { req.WithComment(comment). WithIfNotExists(true) }) @@ -230,32 +261,424 @@ func TestInt_Secrets(t *testing.T) { Name: id.Name(), Comment: comment, SecretType: "PASSWORD", + Username: "", }) assertSecret(t, secret, id, "PASSWORD", comment) }) - t.Run("CreateWithGenericString", func(t *testing.T) { - // TODO: fill me + t.Run("Create: WithGenericString", func(t *testing.T) { + comment := random.Comment() + secret, id := createSecretWithGenericString(t, "foo", func(req *sdk.CreateWithGenericStringSecretRequest) { + req.WithComment(comment). + WithIfNotExists(true) + }) + + assertSecret(t, secret, id, "GENERIC_STRING", comment) + }) + + t.Run("Create: WithGenericString - empty secret_string", func(t *testing.T) { + secret, id := createSecretWithGenericString(t, "", nil) + require.NoError(t, err) + + assertSecret(t, secret, id, "GENERIC_STRING", "") + }) + + t.Run("Alter: SecretWithOAuthClientCredentials", func(t *testing.T) { + comment := random.Comment() + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForOAuthClientCredentialsFlow( + *sdk.NewSetForOAuthClientCredentialsFlowRequest( + []sdk.SecurityIntegrationScope{{"foo"}, {"bar"}}, + ), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + Comment: comment, + OauthScopes: "[foo, bar]", + IntegrationName: integrationId.Name(), + }) + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) + }) + + t.Run("Alter: SecretWithOAuthAuthorizationCode", func(t *testing.T) { + comment := random.Comment() + alteredRefreshTokenExpiryTime := time.Now().Add(4 * Day).Format(time.DateOnly) + + _, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForOAuthAuthorizationFlow( + *sdk.NewSetForOAuthAuthorizationFlowRequest(). + WithOauthRefreshToken("bar"). + WithOauthRefreshTokenExpiryTime(alteredRefreshTokenExpiryTime), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "OAUTH2", + Comment: comment, + OauthRefreshTokenExpiryTime: stringDateToSnowflakeTimeFormat(time.DateOnly, alteredRefreshTokenExpiryTime), + IntegrationName: integrationId.Name(), + }) + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) + }) + + t.Run("Alter: SecretWithBasicAuthorization", func(t *testing.T) { + comment := random.Comment() + + _, id := createSecretWithBasicAuthentication(t, "foo", "foo", nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForBasicAuthentication( + *sdk.NewSetForBasicAuthenticationRequest(). + WithUsername("bar"). + WithPassword("bar"), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + // Cannot check password since show and describe on secret do not have access to password property + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "PASSWORD", + Comment: comment, + Username: "bar", + }) + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) }) - t.Run("Alter", func(t *testing.T) { - // TODO: fill me + t.Run("Alter: SecretWithGenericString", func(t *testing.T) { + comment := random.Comment() + _, id := createSecretWithGenericString(t, "foo", nil) + setRequest := sdk.NewAlterSecretRequest(id). + WithSet( + *sdk.NewSecretSetRequest(). + WithComment(comment). + WithSetForGenericString( + *sdk.NewSetForGenericStringRequest(). + WithSecretString("bar"), + ), + ) + err := client.Secrets.Alter(ctx, setRequest) + require.NoError(t, err) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + /* + // Cannot check secret_string since show and describe on secret do not have access to secret_string property + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + SecretType: "PASSWORD", + Comment: comment, + }) + */ + + unsetRequest := sdk.NewAlterSecretRequest(id). + WithUnset( + *sdk.NewSecretUnsetRequest(). + WithComment(true), + ) + err = client.Secrets.Alter(ctx, unsetRequest) + require.NoError(t, err) + + details, err = client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assert.Equal(t, details.Comment, sql.NullString{"", false}) }) t.Run("Drop", func(t *testing.T) { - // TODO: fill me + _, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NotNil(t, secret) + require.NoError(t, err) + + err = client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id)) + require.NoError(t, err) + + secret, err = client.Secrets.ShowByID(ctx, id) + require.Nil(t, secret) + require.Error(t, err) + }) + + t.Run("Drop: non-existing", func(t *testing.T) { + id := testClientHelper().Ids.RandomSchemaObjectIdentifier() + + err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id)) + assert.ErrorIs(t, err, sdk.ErrObjectNotExistOrAuthorized) }) t.Run("Show", func(t *testing.T) { - // TODO: fill me + secretOAuthClientCredentials, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) + secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest()) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + }) + + t.Run("Show: SecretWithOAuthClientCredentialsFlow with Like", func(t *testing.T) { + secret1, id1 := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secret2, _ := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"bar"}}, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithOAuthAuthorization with Like", func(t *testing.T) { + secret1, id1 := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_1", refreshTokenExpiryTime, nil) + secret2, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo_2", refreshTokenExpiryTime, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithBasicAuthentication with Like", func(t *testing.T) { + secret1, id1 := createSecretWithBasicAuthentication(t, "foo_1", "bar_1", nil) + secret2, _ := createSecretWithBasicAuthentication(t, "foo_2", "bar_2", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithGenericString with Like", func(t *testing.T) { + secret1, id1 := createSecretWithGenericString(t, "foo_1", nil) + secret2, _ := createSecretWithGenericString(t, "foo_2", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithLike(sdk.Like{ + Pattern: sdk.Pointer(id1.Name()), + })) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + }) + + t.Run("Show: SecretWithOAuthClientCredentialsFlow with In", func(t *testing.T) { + secret, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + }) + + t.Run("Show: SecretWithOAuthAuthorizationCodeFlow with In", func(t *testing.T) { + secret, id := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + }) + + t.Run("Show: with In", func(t *testing.T) { + secretOAuthClientCredentials, id := createSecretWithOAuthClientCredentialsFlow(t, integrationId, []sdk.SecurityIntegrationScope{{"foo"}}, nil) + secretOAuthAuthorizationCode, _ := createSecretWithOAuthAuthorizationCodeFlow(t, integrationId, "foo", refreshTokenExpiryTime, nil) + secretBasicAuthentication, _ := createSecretWithBasicAuthentication(t, "foo", "bar", nil) + secretGenericString, _ := createSecretWithGenericString(t, "foo", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secretOAuthClientCredentials) + require.Contains(t, returnedSecrets, *secretOAuthAuthorizationCode) + require.Contains(t, returnedSecrets, *secretBasicAuthentication) + require.Contains(t, returnedSecrets, *secretGenericString) + }) + + t.Run("Show: SecretWithGenericString with In", func(t *testing.T) { + secret, id := createSecretWithGenericString(t, "foo", nil) + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Account: sdk.Pointer(true)})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret) }) t.Run("ShowByID", func(t *testing.T) { - // TODO: fill me + _, id := createSecretWithGenericString(t, "foo", nil) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + assertSecret(t, secret, id, "GENERIC_STRING", "") }) t.Run("Describe", func(t *testing.T) { - // TODO: fill me + _, id := createSecretWithGenericString(t, "foo", func(req *sdk.CreateWithGenericStringSecretRequest) { + req.WithComment("Lorem ipsum") + }) + + details, err := client.Secrets.Describe(ctx, id) + require.NoError(t, err) + + assertSecretDetails(details, secretDetails{ + Name: id.Name(), + Comment: "Lorem ipsum", + SecretType: "GENERIC_STRING", + }) + }) +} + +func TestInt_SecretsShowWithIn(t *testing.T) { + client := testClient(t) + ctx := testContext(t) + + cleanupSecret := func(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + return func() { + err := client.Secrets.Drop(ctx, sdk.NewDropSecretRequest(id).WithIfExists(true)) + require.NoError(t, err) + } + } + + createSecretWithGenericString := func(t *testing.T, id sdk.SchemaObjectIdentifier, secretString string) *sdk.Secret { + t.Helper() + request := sdk.NewCreateWithGenericStringSecretRequest(id, secretString) + err := client.Secrets.CreateWithGenericString(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupSecret(t, id)) + + secret, err := client.Secrets.ShowByID(ctx, id) + require.NoError(t, err) + + return secret + } + + t.Run("Show with In - same id in different schemas", func(t *testing.T) { + schema, schemaCleanup := testClientHelper().Schema.CreateSchema(t) + t.Cleanup(schemaCleanup) + + id1 := testClientHelper().Ids.RandomSchemaObjectIdentifier() + id2 := testClientHelper().Ids.NewSchemaObjectIdentifierInSchema(id1.Name(), schema.ID()) + + secret1 := createSecretWithGenericString(t, id1, "foo") + secret2 := createSecretWithGenericString(t, id2, "bar") + + returnedSecrets, err := client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Schema: id1.SchemaId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.NotContains(t, returnedSecrets, *secret2) + + returnedSecrets, err = client.Secrets.Show(ctx, sdk.NewShowSecretRequest().WithIn(sdk.In{Database: id1.DatabaseId()})) + require.NoError(t, err) + require.Contains(t, returnedSecrets, *secret1) + require.Contains(t, returnedSecrets, *secret2) }) + }