Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 8 additions & 1 deletion docs/resources/realm.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,16 @@ This block supports the following arguments:
- `envelope_from` - (Optional) The email address uses for bounces.
- `starttls` - (Optional) When `true`, enables StartTLS. Defaults to `false`.
- `ssl` - (Optional) When `true`, enables SSL. Defaults to `false`.
- `auth` - (Optional) Enables authentication to the SMTP server. This block supports the following arguments:
- `auth` - (Optional) Enables authentication to the SMTP server. Cannot be set alongside `token_auth`. This block supports the following arguments:
- `username` - (Required) The SMTP server username.
- `password` - (Required) The SMTP server password.
- `token_auth` - (Optional) Enables authentication to the SMTP server through OAUTH2. Cannot be set alongside `auth`. This block supports the following arguments:
- `username` - (Required) The SMTP server username.
- `url` - (Required) The auth token URL.
- `client_id` - (Required) The auth token client ID.
- `client_secret` - (Required) The auth token client secret.
- `scope` - (Required) The auth token scope.


### Internationalization

Expand Down
29 changes: 17 additions & 12 deletions keycloak/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,18 +158,23 @@ type BrowserSecurityHeaders struct {
}

type SmtpServer struct {
StartTls types.KeycloakBoolQuoted `json:"starttls,omitempty"`
Auth types.KeycloakBoolQuoted `json:"auth,omitempty"`
Port string `json:"port,omitempty"`
Host string `json:"host,omitempty"`
ReplyTo string `json:"replyTo,omitempty"`
ReplyToDisplayName string `json:"replyToDisplayName,omitempty"`
From string `json:"from,omitempty"`
FromDisplayName string `json:"fromDisplayName,omitempty"`
EnvelopeFrom string `json:"envelopeFrom,omitempty"`
Ssl types.KeycloakBoolQuoted `json:"ssl,omitempty"`
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
StartTls types.KeycloakBoolQuoted `json:"starttls,omitempty"`
Auth types.KeycloakBoolQuoted `json:"auth,omitempty"`
Port string `json:"port,omitempty"`
Host string `json:"host,omitempty"`
ReplyTo string `json:"replyTo,omitempty"`
ReplyToDisplayName string `json:"replyToDisplayName,omitempty"`
From string `json:"from,omitempty"`
FromDisplayName string `json:"fromDisplayName,omitempty"`
EnvelopeFrom string `json:"envelopeFrom,omitempty"`
Ssl types.KeycloakBoolQuoted `json:"ssl,omitempty"`
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
AuthType string `json:"authType,omitempty"`
AuthTokenUrl string `json:"authTokenUrl,omitempty"`
AuthTokenClientId string `json:"authTokenClientId,omitempty"`
AuthTokenClientSecret string `json:"authTokenClientSecret,omitempty"`
AuthTokenScope string `json:"authTokenScope,omitempty"`
}

func (keycloakClient *KeycloakClient) NewRealm(ctx context.Context, realm *Realm) error {
Expand Down
30 changes: 30 additions & 0 deletions provider/data_source_keycloak_realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,36 @@ func dataSourceKeycloakRealm() *schema.Resource {
},
},
},
"token_auth": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"username": {
Type: schema.TypeString,
Computed: true,
},
"url": {
Type: schema.TypeString,
Computed: true,
},
"client_id": {
Type: schema.TypeString,
Computed: true,
},
"client_secret": {
Type: schema.TypeString,
Computed: true,
Sensitive: true,
},
"scope": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
},
},
Expand Down
74 changes: 67 additions & 7 deletions provider/resource_keycloak_realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,10 @@ func resourceKeycloakRealm() *schema.Resource {
Optional: true,
},
"auth": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Type: schema.TypeList,
Optional: true,
ConflictsWith: []string{"smtp_server.0.token_auth"},
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"username": {
Expand All @@ -306,6 +307,40 @@ func resourceKeycloakRealm() *schema.Resource {
},
},
},
"token_auth": {
Type: schema.TypeList,
Optional: true,
ConflictsWith: []string{"smtp_server.0.auth"},
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"username": {
Type: schema.TypeString,
Required: true,
},
"url": {
Type: schema.TypeString,
Required: true,
},
"client_id": {
Type: schema.TypeString,
Required: true,
},
"client_secret": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
DiffSuppressFunc: func(_, authTokenClientSecret, _ string, _ *schema.ResourceData) bool {
return authTokenClientSecret == "**********"
},
},
"scope": {
Type: schema.TypeString,
Required: true,
},
},
},
},
},
},
},
Expand Down Expand Up @@ -809,12 +844,25 @@ func getRealmFromData(data *schema.ResourceData, keycloakVersion *version.Versio
}

authConfig := smtpSettings["auth"].([]interface{})
tokenAuthConfig := smtpSettings["token_auth"].([]interface{})

if len(authConfig) == 1 {
auth := authConfig[0].(map[string]interface{})

smtpServer.Auth = true
smtpServer.AuthType = "basic"
smtpServer.User = auth["username"].(string)
smtpServer.Password = auth["password"].(string)
} else if len(tokenAuthConfig) == 1 {
tokenAuth := tokenAuthConfig[0].(map[string]interface{})

smtpServer.Auth = true
smtpServer.AuthType = "token"
smtpServer.User = tokenAuth["username"].(string)
smtpServer.AuthTokenUrl = tokenAuth["url"].(string)
smtpServer.AuthTokenClientId = tokenAuth["client_id"].(string)
smtpServer.AuthTokenClientSecret = tokenAuth["client_secret"].(string)
smtpServer.AuthTokenScope = tokenAuth["scope"].(string)
} else {
smtpServer.Auth = false
}
Expand Down Expand Up @@ -1241,12 +1289,24 @@ func setRealmData(data *schema.ResourceData, realm *keycloak.Realm, keycloakVers
smtpSettings["ssl"] = realm.SmtpServer.Ssl

if realm.SmtpServer.Auth {
auth := make(map[string]interface{})
if realm.SmtpServer.AuthType == "token" {
token_auth := make(map[string]interface{})

token_auth["username"] = realm.SmtpServer.User
token_auth["url"] = realm.SmtpServer.AuthTokenUrl
token_auth["client_id"] = realm.SmtpServer.AuthTokenClientId
token_auth["client_secret"] = realm.SmtpServer.AuthTokenClientSecret
token_auth["scope"] = realm.SmtpServer.AuthTokenScope

auth["username"] = realm.SmtpServer.User
auth["password"] = realm.SmtpServer.Password
smtpSettings["token_auth"] = []interface{}{token_auth}
} else {
auth := make(map[string]interface{})

smtpSettings["auth"] = []interface{}{auth}
auth["username"] = realm.SmtpServer.User
auth["password"] = realm.SmtpServer.Password

smtpSettings["auth"] = []interface{}{auth}
}
}

data.Set("smtp_server", []interface{}{smtpSettings})
Expand Down
68 changes: 68 additions & 0 deletions provider/resource_keycloak_realm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,46 @@ func TestAccKeycloakRealm_SmtpServerUpdate(t *testing.T) {
},
})
}
func TestAccKeycloakRealm_SmtpServerOauth(t *testing.T) {
realm := acctest.RandomWithPrefix("tf-acc")
realmDisplayNameHtml := acctest.RandomWithPrefix("tf-acc")

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakRealmDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakRealm_WithSmtpServerWithOauth(realm, "myhost.com", "My Host", "user"),
Check: testAccCheckKeycloakRealmSmtp("keycloak_realm.realm", "myhost.com", "My Host", "user"),
},
{
Config: testKeycloakRealm_basic(realm, realm, realmDisplayNameHtml),
Check: testAccCheckKeycloakRealmSmtp("keycloak_realm.realm", "", "", ""),
},
},
})
}

func TestAccKeycloakRealm_SmtpServerOauthUpdate(t *testing.T) {
realm := acctest.RandomWithPrefix("tf-acc")

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakRealmDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakRealm_WithSmtpServerWithOauth(realm, "myhost.com", "My Host", "user"),
Check: testAccCheckKeycloakRealmSmtp("keycloak_realm.realm", "myhost.com", "My Host", "user"),
},
{
Config: testKeycloakRealm_WithSmtpServerWithOauth(realm, "myhost2.com", "My Host2", "user2"),
Check: testAccCheckKeycloakRealmSmtp("keycloak_realm.realm", "myhost2.com", "My Host2", "user2"),
},
},
})
}

func TestAccKeycloakRealm_SmtpServerInvalid(t *testing.T) {
realm := acctest.RandomWithPrefix("tf-acc")
Expand Down Expand Up @@ -1344,6 +1384,34 @@ resource "keycloak_realm" "realm" {
`, realm, realm, host, from, user)
}

func testKeycloakRealm_WithSmtpServerWithOauth(realm, host, from, user string) string {
return fmt.Sprintf(`
resource "keycloak_realm" "realm" {
realm = "%s"
enabled = true
display_name = "%s"
smtp_server {
host = "%s"
port = 25
from_display_name = "Tom"
from = "%s"
reply_to_display_name = "Tom"
reply_to = "[email protected]"
ssl = true
starttls = true
envelope_from = "[email protected]"
token_auth {
username = "%s"
url = "wibble.com"
client_id = "wibble"
client_secret = "wobble"
scope = "wiggle"
}
}
}
`, realm, realm, host, from, user)
}

func testKeycloakRealm_WithOTP(realm, otpType, algorithm string, period int) string {
return fmt.Sprintf(`
resource "keycloak_realm" "realm" {
Expand Down