Skip to content

Commit

Permalink
Common changes
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-jmichalak committed Jun 27, 2024
1 parent 1cada88 commit c471a3c
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 17 deletions.
12 changes: 10 additions & 2 deletions pkg/acceptance/helpers/random/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/pem"
"fmt"
"math/big"
Expand Down Expand Up @@ -39,15 +41,21 @@ func GenerateX509(t *testing.T) string {
}

// GenerateRSA returns an RSA public key without BEGIN and END markers.
func GenerateRSAPublicKey(t *testing.T) string {
func GenerateRSAPublicKey(t *testing.T) (string, string) {
t.Helper()
key, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err)

pub := key.Public()
b, err := x509.MarshalPKIXPublicKey(pub.(*rsa.PublicKey))
require.NoError(t, err)
return encode(t, "RSA PUBLIC KEY", b)
return encode(t, "RSA PUBLIC KEY", b), fmt.Sprintf("SHA256:%s", hash(t, b))
}

func hash(t *testing.T, b []byte) string {
t.Helper()
hash := sha256.Sum256(b)
return base64.StdEncoding.EncodeToString(hash[:])
}

func encode(t *testing.T, pemType string, b []byte) string {
Expand Down
51 changes: 51 additions & 0 deletions pkg/resources/common.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package resources

import (
"context"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"strings"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

Expand Down Expand Up @@ -52,3 +62,44 @@ func suppressCopyOptionsQuoting(_, oldValue, newValue string, _ *schema.Resource
return oldWithoutQuotes == newWithoutQuotes
}
}

func DeleteContextSecurityIntegration(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier)
client := meta.(*provider.Context).Client

err := client.SecurityIntegrations.Drop(ctx, sdk.NewDropSecurityIntegrationRequest(sdk.NewAccountObjectIdentifier(id.Name())).WithIfExists(true))
if err != nil {
return diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Error,
Summary: "Error deleting integration",
Detail: fmt.Sprintf("id %v err = %v", id.Name(), err),
},
}
}

d.SetId("")
return nil
}

func RSAKeyHash(key string) (string, error) {
keyBytes := []byte(fmt.Sprintf("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", key))

block, _ := pem.Decode(keyBytes)
if block == nil || block.Type != "PUBLIC KEY" {
return "", errors.New("Failed to decode PEM block containing public key")
}

pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("Unable to parse public key: %w", err)
}

pubKeyBytes, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
return "", fmt.Errorf("Unable to marshal public key: %w", err)
}

hash := sha256.Sum256(pubKeyBytes)
return fmt.Sprintf("SHA256:%s", base64.StdEncoding.EncodeToString(hash[:])), nil
}
165 changes: 153 additions & 12 deletions pkg/sdk/security_integrations_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,47 @@ const (
OauthSecurityIntegrationUseSecondaryRolesNone OauthSecurityIntegrationUseSecondaryRolesOption = "NONE"
)

var AllOauthSecurityIntegrationUseSecondaryRoles = []OauthSecurityIntegrationUseSecondaryRolesOption{
OauthSecurityIntegrationUseSecondaryRolesImplicit,
OauthSecurityIntegrationUseSecondaryRolesNone,
}

func ToOauthSecurityIntegrationUseSecondaryRolesOption(s string) (OauthSecurityIntegrationUseSecondaryRolesOption, error) {
s = strings.ToUpper(s)
switch s {
case string(OauthSecurityIntegrationUseSecondaryRolesImplicit):
return OauthSecurityIntegrationUseSecondaryRolesImplicit, nil
case string(OauthSecurityIntegrationUseSecondaryRolesNone):
return OauthSecurityIntegrationUseSecondaryRolesNone, nil
default:
return "", fmt.Errorf("invalid OauthSecurityIntegrationUseSecondaryRolesOption: %s", s)
}
}

type OauthSecurityIntegrationClientTypeOption string

const (
OauthSecurityIntegrationClientTypePublic OauthSecurityIntegrationClientTypeOption = "PUBLIC"
OauthSecurityIntegrationClientTypeConfidential OauthSecurityIntegrationClientTypeOption = "CONFIDENTIAL"
)

var AllOauthSecurityIntegrationClientTypes = []OauthSecurityIntegrationClientTypeOption{
OauthSecurityIntegrationClientTypePublic,
OauthSecurityIntegrationClientTypeConfidential,
}

func ToOauthSecurityIntegrationClientTypeOption(s string) (OauthSecurityIntegrationClientTypeOption, error) {
s = strings.ToUpper(s)
switch s {
case string(OauthSecurityIntegrationClientTypePublic):
return OauthSecurityIntegrationClientTypePublic, nil
case string(OauthSecurityIntegrationClientTypeConfidential):
return OauthSecurityIntegrationClientTypeConfidential, nil
default:
return "", fmt.Errorf("invalid OauthSecurityIntegrationClientTypeOption: %s", s)
}
}

type OauthSecurityIntegrationClientOption string

const (
Expand All @@ -63,6 +97,97 @@ const (
OauthSecurityIntegrationClientTableauServer OauthSecurityIntegrationClientOption = "TABLEAU_SERVER"
)

var AllOauthSecurityIntegrationClients = []OauthSecurityIntegrationClientOption{
OauthSecurityIntegrationClientLooker,
OauthSecurityIntegrationClientTableauDesktop,
OauthSecurityIntegrationClientTableauServer,
}

func ToOauthSecurityIntegrationClientOption(s string) (OauthSecurityIntegrationClientOption, error) {
s = strings.ToUpper(s)
switch s {
case string(OauthSecurityIntegrationClientLooker):
return OauthSecurityIntegrationClientLooker, nil
case string(OauthSecurityIntegrationClientTableauDesktop):
return OauthSecurityIntegrationClientTableauDesktop, nil
case string(OauthSecurityIntegrationClientTableauServer):
return OauthSecurityIntegrationClientTableauServer, nil
default:
return "", fmt.Errorf("invalid OauthSecurityIntegrationClientOption: %s", s)
}
}

type Saml2SecurityIntegrationSaml2ProviderOption string

const (
Saml2SecurityIntegrationSaml2ProviderOkta Saml2SecurityIntegrationSaml2ProviderOption = "OKTA"
Saml2SecurityIntegrationSaml2ProviderAdfs Saml2SecurityIntegrationSaml2ProviderOption = "ADFS"
Saml2SecurityIntegrationSaml2ProviderCustom Saml2SecurityIntegrationSaml2ProviderOption = "CUSTOM"
)

var AllSaml2SecurityIntegrationSaml2Providers = []Saml2SecurityIntegrationSaml2ProviderOption{
Saml2SecurityIntegrationSaml2ProviderOkta,
Saml2SecurityIntegrationSaml2ProviderAdfs,
Saml2SecurityIntegrationSaml2ProviderCustom,
}

func ToSaml2SecurityIntegrationSaml2ProviderOption(s string) (Saml2SecurityIntegrationSaml2ProviderOption, error) {
s = strings.ToUpper(s)
switch s {
case string(Saml2SecurityIntegrationSaml2ProviderOkta):
return Saml2SecurityIntegrationSaml2ProviderOkta, nil
case string(Saml2SecurityIntegrationSaml2ProviderAdfs):
return Saml2SecurityIntegrationSaml2ProviderAdfs, nil
case string(Saml2SecurityIntegrationSaml2ProviderCustom):
return Saml2SecurityIntegrationSaml2ProviderCustom, nil
default:
return "", fmt.Errorf("invalid Saml2SecurityIntegrationSaml2ProviderOption: %s", s)
}
}

type Saml2SecurityIntegrationSaml2RequestedNameidFormatOption string

const (
Saml2SecurityIntegrationSaml2RequestedNameidFormatUnspecified Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
Saml2SecurityIntegrationSaml2RequestedNameidFormatEmailAddress Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
Saml2SecurityIntegrationSaml2RequestedNameidFormatX509SubjectName Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"
Saml2SecurityIntegrationSaml2RequestedNameidFormatWindowsDomainQualifiedName Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"
Saml2SecurityIntegrationSaml2RequestedNameidFormatKerberos Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"
Saml2SecurityIntegrationSaml2RequestedNameidFormatPersistent Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
Saml2SecurityIntegrationSaml2RequestedNameidFormatTransient Saml2SecurityIntegrationSaml2RequestedNameidFormatOption = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
)

var AllSaml2SecurityIntegrationSaml2RequestedNameidFormats = []Saml2SecurityIntegrationSaml2RequestedNameidFormatOption{
Saml2SecurityIntegrationSaml2RequestedNameidFormatUnspecified,
Saml2SecurityIntegrationSaml2RequestedNameidFormatEmailAddress,
Saml2SecurityIntegrationSaml2RequestedNameidFormatX509SubjectName,
Saml2SecurityIntegrationSaml2RequestedNameidFormatWindowsDomainQualifiedName,
Saml2SecurityIntegrationSaml2RequestedNameidFormatKerberos,
Saml2SecurityIntegrationSaml2RequestedNameidFormatPersistent,
Saml2SecurityIntegrationSaml2RequestedNameidFormatTransient,
}

func ToSaml2SecurityIntegrationSaml2RequestedNameidFormatOption(s string) (Saml2SecurityIntegrationSaml2RequestedNameidFormatOption, error) {
switch s {
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatUnspecified):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatUnspecified, nil
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatEmailAddress):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatEmailAddress, nil
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatX509SubjectName):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatX509SubjectName, nil
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatWindowsDomainQualifiedName):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatWindowsDomainQualifiedName, nil
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatKerberos):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatKerberos, nil
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatPersistent):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatPersistent, nil
case string(Saml2SecurityIntegrationSaml2RequestedNameidFormatTransient):
return Saml2SecurityIntegrationSaml2RequestedNameidFormatTransient, nil
default:
return "", fmt.Errorf("invalid Saml2SecurityIntegrationSaml2RequestedNameidFormatOption: %s", s)
}
}

type ScimSecurityIntegrationScimClientOption string

const (
Expand All @@ -80,11 +205,11 @@ var AllScimSecurityIntegrationScimClients = []ScimSecurityIntegrationScimClientO
func ToScimSecurityIntegrationScimClientOption(s string) (ScimSecurityIntegrationScimClientOption, error) {
s = strings.ToUpper(s)
switch s {
case "OKTA":
case string(ScimSecurityIntegrationScimClientOkta):
return ScimSecurityIntegrationScimClientOkta, nil
case "AZURE":
case string(ScimSecurityIntegrationScimClientAzure):
return ScimSecurityIntegrationScimClientAzure, nil
case "GENERIC":
case string(ScimSecurityIntegrationScimClientGeneric):
return ScimSecurityIntegrationScimClientGeneric, nil
default:
return "", fmt.Errorf("invalid ScimSecurityIntegrationScimClientOption: %s", s)
Expand All @@ -108,11 +233,11 @@ var AllScimSecurityIntegrationRunAsRoles = []ScimSecurityIntegrationRunAsRoleOpt
func ToScimSecurityIntegrationRunAsRoleOption(s string) (ScimSecurityIntegrationRunAsRoleOption, error) {
s = strings.ToUpper(s)
switch s {
case "OKTA_PROVISIONER":
case string(ScimSecurityIntegrationRunAsRoleOktaProvisioner):
return ScimSecurityIntegrationRunAsRoleOktaProvisioner, nil
case "AAD_PROVISIONER":
case string(ScimSecurityIntegrationRunAsRoleAadProvisioner):
return ScimSecurityIntegrationRunAsRoleAadProvisioner, nil
case "GENERIC_SCIM_PROVISIONER":
case string(ScimSecurityIntegrationRunAsRoleGenericScimProvisioner):
return ScimSecurityIntegrationRunAsRoleGenericScimProvisioner, nil
default:
return "", fmt.Errorf("invalid ScimSecurityIntegrationRunAsRoleOption: %s", s)
Expand Down Expand Up @@ -325,15 +450,23 @@ var saml2IntegrationSetDef = g.NewQueryStruct("Saml2IntegrationSet").
OptionalBooleanAssignment("ENABLED", g.ParameterOptions()).
OptionalTextAssignment("SAML2_ISSUER", g.ParameterOptions().SingleQuotes()).
OptionalTextAssignment("SAML2_SSO_URL", g.ParameterOptions().SingleQuotes()).
OptionalTextAssignment("SAML2_PROVIDER", g.ParameterOptions().SingleQuotes()).
OptionalAssignment(
"SAML2_PROVIDER",
g.KindOfT[Saml2SecurityIntegrationSaml2ProviderOption](),
g.ParameterOptions().SingleQuotes(),
).
OptionalTextAssignment("SAML2_X509_CERT", g.ParameterOptions().SingleQuotes()).
ListAssignment("ALLOWED_USER_DOMAINS", "UserDomain", g.ParameterOptions().Parentheses()).
ListAssignment("ALLOWED_EMAIL_PATTERNS", "EmailPattern", g.ParameterOptions().Parentheses()).
OptionalTextAssignment("SAML2_SP_INITIATED_LOGIN_PAGE_LABEL", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("SAML2_ENABLE_SP_INITIATED", g.ParameterOptions()).
OptionalTextAssignment("SAML2_SNOWFLAKE_X509_CERT", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("SAML2_SIGN_REQUEST", g.ParameterOptions()).
OptionalTextAssignment("SAML2_REQUESTED_NAMEID_FORMAT", g.ParameterOptions().SingleQuotes()).
OptionalAssignment(
"SAML2_REQUESTED_NAMEID_FORMAT",
g.KindOfT[Saml2SecurityIntegrationSaml2RequestedNameidFormatOption](),
g.ParameterOptions().SingleQuotes(),
).
OptionalTextAssignment("SAML2_POST_LOGOUT_REDIRECT_URL", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("SAML2_FORCE_AUTHN", g.ParameterOptions()).
OptionalTextAssignment("SAML2_SNOWFLAKE_ISSUER_URL", g.ParameterOptions().SingleQuotes()).
Expand Down Expand Up @@ -517,7 +650,7 @@ var SecurityIntegrationsDef = g.NewInterface(
g.KindOfT[OauthSecurityIntegrationClientTypeOption](),
g.ParameterOptions().Required().SingleQuotes(),
).
TextAssignment("OAUTH_REDIRECT_URI", g.ParameterOptions().Required().SingleQuotes()).
OptionalTextAssignment("OAUTH_REDIRECT_URI", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("ENABLED", g.ParameterOptions()).
OptionalBooleanAssignment("OAUTH_ALLOW_NON_TLS_REDIRECT_URI", g.ParameterOptions()).
OptionalBooleanAssignment("OAUTH_ENFORCE_PKCE", g.ParameterOptions()).
Expand All @@ -541,18 +674,26 @@ var SecurityIntegrationsDef = g.NewInterface(
createSecurityIntegrationOperation("CreateSaml2", func(qs *g.QueryStruct) *g.QueryStruct {
return qs.
PredefinedQueryStructField("integrationType", "string", g.StaticOptions().SQL("TYPE = SAML2")).
BooleanAssignment("ENABLED", g.ParameterOptions().Required()).
OptionalBooleanAssignment("ENABLED", g.ParameterOptions()).
TextAssignment("SAML2_ISSUER", g.ParameterOptions().Required().SingleQuotes()).
TextAssignment("SAML2_SSO_URL", g.ParameterOptions().Required().SingleQuotes()).
TextAssignment("SAML2_PROVIDER", g.ParameterOptions().Required().SingleQuotes()).
Assignment(
"SAML2_PROVIDER",
g.KindOfT[Saml2SecurityIntegrationSaml2ProviderOption](),
g.ParameterOptions().Required().SingleQuotes(),
).
TextAssignment("SAML2_X509_CERT", g.ParameterOptions().Required().SingleQuotes()).
ListAssignment("ALLOWED_USER_DOMAINS", "UserDomain", g.ParameterOptions().Parentheses()).
ListAssignment("ALLOWED_EMAIL_PATTERNS", "EmailPattern", g.ParameterOptions().Parentheses()).
OptionalTextAssignment("SAML2_SP_INITIATED_LOGIN_PAGE_LABEL", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("SAML2_ENABLE_SP_INITIATED", g.ParameterOptions()).
OptionalTextAssignment("SAML2_SNOWFLAKE_X509_CERT", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("SAML2_SIGN_REQUEST", g.ParameterOptions()).
OptionalTextAssignment("SAML2_REQUESTED_NAMEID_FORMAT", g.ParameterOptions().SingleQuotes()).
OptionalAssignment(
"SAML2_REQUESTED_NAMEID_FORMAT",
g.KindOfT[Saml2SecurityIntegrationSaml2RequestedNameidFormatOption](),
g.ParameterOptions().SingleQuotes(),
).
OptionalTextAssignment("SAML2_POST_LOGOUT_REDIRECT_URL", g.ParameterOptions().SingleQuotes()).
OptionalBooleanAssignment("SAML2_FORCE_AUTHN", g.ParameterOptions()).
OptionalTextAssignment("SAML2_SNOWFLAKE_ISSUER_URL", g.ParameterOptions().SingleQuotes()).
Expand Down
4 changes: 2 additions & 2 deletions pkg/sdk/testint/security_integrations_gen_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestInt_SecurityIntegrations(t *testing.T) {
acsURL := testClientHelper().Context.ACSURL(t)
issuerURL := testClientHelper().Context.IssuerURL(t)
cert := random.GenerateX509(t)
rsaKey := random.GenerateRSAPublicKey(t)
rsaKey, _ := random.GenerateRSAPublicKey(t)

revertParameter := testClientHelper().Parameter.UpdateAccountParameterTemporarily(t, sdk.AccountParameterEnableIdentifierFirstLogin, "true")
t.Cleanup(revertParameter)
Expand Down Expand Up @@ -135,7 +135,7 @@ func TestInt_SecurityIntegrations(t *testing.T) {
}
err := client.SecurityIntegrations.CreateSaml2(ctx, saml2Req)
require.NoError(t, err)
cleanupSecurityIntegration(t, id)
// cleanupSecurityIntegration(t, id)
integration, err := client.SecurityIntegrations.ShowByID(ctx, id)
require.NoError(t, err)

Expand Down
Loading

0 comments on commit c471a3c

Please sign in to comment.