Skip to content

Commit e4fa946

Browse files
committed
feat(keycloak_saml_client_installation_provider): support zip files
Signed-off-by: Jules Casteran <[email protected]>
1 parent 91266a0 commit e4fa946

File tree

3 files changed

+90
-9
lines changed

3 files changed

+90
-9
lines changed

docs/data-sources/saml_client_installation_provider.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ resource "aws_iam_saml_provider" "default" {
5252

5353
- `id` - (Computed) The hash of the value.
5454
- `value` - (Computed) The returned document needed for SAML installation.
55+
- `zip_files` - (Computed) A map of files if the returned document is a zip file. (ex: provider `mod-auth-mellon`)

provider/data_source_keycloak_saml_client_installation_provider.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package provider
22

33
import (
4+
"archive/zip"
5+
"bytes"
46
"context"
57
"crypto/sha1"
68
"encoding/base64"
9+
"errors"
10+
"fmt"
11+
"io"
12+
713
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
814
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
915
"github.com/keycloak/terraform-provider-keycloak/keycloak"
@@ -29,6 +35,13 @@ func dataSourceKeycloakSamlClientInstallationProvider() *schema.Resource {
2935
Type: schema.TypeString,
3036
Computed: true,
3137
},
38+
"zip_files": {
39+
Type: schema.TypeMap,
40+
Computed: true,
41+
Elem: &schema.Schema{
42+
Type: schema.TypeString,
43+
},
44+
},
3245
},
3346
}
3447
}
@@ -55,5 +68,42 @@ func dataSourceKeycloakSamlClientInstallationProviderRead(ctx context.Context, d
5568
data.Set("provider_id", providerId)
5669
data.Set("value", string(value))
5770

71+
zipFiles, err := readZipFiles(value)
72+
if err != nil {
73+
return diag.FromErr(err)
74+
}
75+
data.Set("zip_files", zipFiles)
76+
5877
return nil
5978
}
79+
80+
func readZipFiles(content []byte) (map[string]string, error) {
81+
zipReader, err := zip.NewReader(bytes.NewReader(content), int64(len(content)))
82+
if err != nil {
83+
if errors.Is(err, zip.ErrFormat) {
84+
return nil, nil
85+
}
86+
87+
return nil, fmt.Errorf("error reading zip files: %w", err)
88+
}
89+
90+
files := make(map[string]string, len(zipReader.File))
91+
for _, file := range zipReader.File {
92+
fileReader, err := file.Open()
93+
if err != nil {
94+
return nil, fmt.Errorf("error opening zip file for reading: %w", err)
95+
}
96+
fileContent, err := io.ReadAll(fileReader)
97+
if err != nil {
98+
return nil, fmt.Errorf("error reading zip file content: %w", err)
99+
}
100+
files[file.FileInfo().Name()] = string(fileContent)
101+
102+
err = fileReader.Close()
103+
if err != nil {
104+
return nil, fmt.Errorf("error closing zip file content: %w", err)
105+
}
106+
}
107+
108+
return files, nil
109+
}

provider/data_source_keycloak_saml_client_installation_provider_test.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,64 @@ func TestAccKeycloakDataSourceSamlClientInstallationProvider_basic(t *testing.T)
1515
clientId := acctest.RandomWithPrefix("tf-acc")
1616

1717
resourceName := "keycloak_saml_client.saml_client"
18-
dataSourceName := "data.keycloak_saml_client_installation_provider.saml_sp_descriptor"
18+
dataSourceName := "data.keycloak_saml_client_installation_provider.descriptor"
1919

2020
resource.Test(t, resource.TestCase{
2121
ProviderFactories: testAccProviderFactories,
2222
PreCheck: func() { testAccPreCheck(t) },
2323
CheckDestroy: testAccCheckKeycloakSamlClientDestroy(),
2424
Steps: []resource.TestStep{
2525
{
26-
Config: testDataSourceKeycloakSamlClientInstallationProvider_basic(clientId),
26+
Config: testDataSourceKeycloakSamlClientInstallationProvider(clientId, "saml-sp-descriptor"),
2727
Check: resource.ComposeTestCheckFunc(
2828
resource.TestCheckResourceAttrPair(dataSourceName, "realm_id", resourceName, "realm_id"),
2929
resource.TestCheckResourceAttrPair(dataSourceName, "client_id", resourceName, "id"),
3030
resource.TestCheckResourceAttr(dataSourceName, "provider_id", "saml-sp-descriptor"),
31-
testAccCheckDataKeycloakSamlClientInstallationProvider(dataSourceName),
31+
resource.TestCheckResourceAttr(dataSourceName, "zip_files.%", "0"),
32+
testAccCheckDataKeycloakSamlClientInstallationProvider_isXML(dataSourceName, "value"),
3233
),
3334
},
3435
},
3536
})
3637
}
3738

38-
func testAccCheckDataKeycloakSamlClientInstallationProvider(resourceName string) resource.TestCheckFunc {
39+
func TestAccKeycloakDataSourceSamlClientInstallationProvider_zip(t *testing.T) {
40+
t.Parallel()
41+
clientId := acctest.RandomWithPrefix("tf-acc")
42+
43+
resourceName := "keycloak_saml_client.saml_client"
44+
dataSourceName := "data.keycloak_saml_client_installation_provider.descriptor"
45+
46+
resource.Test(t, resource.TestCase{
47+
ProviderFactories: testAccProviderFactories,
48+
PreCheck: func() { testAccPreCheck(t) },
49+
CheckDestroy: testAccCheckKeycloakSamlClientDestroy(),
50+
Steps: []resource.TestStep{
51+
{
52+
Config: testDataSourceKeycloakSamlClientInstallationProvider(clientId, "mod-auth-mellon"),
53+
Check: resource.ComposeTestCheckFunc(
54+
resource.TestCheckResourceAttrPair(dataSourceName, "realm_id", resourceName, "realm_id"),
55+
resource.TestCheckResourceAttrPair(dataSourceName, "client_id", resourceName, "id"),
56+
resource.TestCheckResourceAttr(dataSourceName, "provider_id", "mod-auth-mellon"),
57+
resource.TestCheckResourceAttr(dataSourceName, "zip_files.%", "4"),
58+
testAccCheckDataKeycloakSamlClientInstallationProvider_isXML(dataSourceName, "zip_files.idp-metadata.xml"),
59+
testAccCheckDataKeycloakSamlClientInstallationProvider_isXML(dataSourceName, "zip_files.sp-metadata.xml"),
60+
resource.TestCheckResourceAttrSet(dataSourceName, "zip_files.client-cert.pem"),
61+
resource.TestCheckResourceAttrSet(dataSourceName, "zip_files.client-private-key.pem"),
62+
),
63+
},
64+
},
65+
})
66+
}
67+
68+
func testAccCheckDataKeycloakSamlClientInstallationProvider_isXML(resourceName string, attributeName string) resource.TestCheckFunc {
3969
return func(s *terraform.State) error {
4070
rs, ok := s.RootModule().Resources[resourceName]
4171
if !ok {
4272
return fmt.Errorf("resource not found: %s", resourceName)
4373
}
4474

45-
value := rs.Primary.Attributes["value"]
75+
value := rs.Primary.Attributes[attributeName]
4676

4777
err := xml.Unmarshal([]byte(value), new(interface{}))
4878
if err != nil {
@@ -53,7 +83,7 @@ func testAccCheckDataKeycloakSamlClientInstallationProvider(resourceName string)
5383
}
5484
}
5585

56-
func testDataSourceKeycloakSamlClientInstallationProvider_basic(clientId string) string {
86+
func testDataSourceKeycloakSamlClientInstallationProvider(clientId string, providerId string) string {
5787
return fmt.Sprintf(`
5888
data "keycloak_realm" "realm" {
5989
realm = "%s"
@@ -64,10 +94,10 @@ resource "keycloak_saml_client" "saml_client" {
6494
realm_id = data.keycloak_realm.realm.id
6595
}
6696
67-
data "keycloak_saml_client_installation_provider" "saml_sp_descriptor" {
97+
data "keycloak_saml_client_installation_provider" "descriptor" {
6898
realm_id = data.keycloak_realm.realm.id
6999
client_id = keycloak_saml_client.saml_client.id
70-
provider_id = "saml-sp-descriptor"
100+
provider_id = "%s"
71101
}
72-
`, testAccRealm.Realm, clientId)
102+
`, testAccRealm.Realm, clientId, providerId)
73103
}

0 commit comments

Comments
 (0)