Skip to content

Commit

Permalink
support for brute-force-detetcion-settings + support for ssl_required…
Browse files Browse the repository at this point in the history
… + support for custom-realm-attributes + bugfix for keycloak#174
  • Loading branch information
Tom Rutsaert committed Dec 6, 2019
1 parent 2aff30a commit 340823e
Show file tree
Hide file tree
Showing 8 changed files with 493 additions and 76 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ GO111MODULE=on go mod download && make build

## Supported Versions

Currently, this provider is tested against Terraform v0.12.1 and Keycloak v7.0.0. I personally use this provider with Terraform v0.11.x and Keycloak 4.8.3.Final.
Currently, this provider is tested against Terraform v0.12.1 and Keycloak v8.0.0. I personally use this provider with Terraform v0.11.x and Keycloak 4.8.3.Final.

In the future, it would be nice to [run acceptance tests using different versions of Terraform / Keycloak](https://github.com/mrparkers/terraform-provider-keycloak/issues/111). Please feel free to submit a PR if you believe you can help with this.

Expand Down
12 changes: 6 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ services:
ports:
- 8389:389
keycloak:
image: jboss/keycloak:7.0.0
image: jboss/keycloak:8.0.0
depends_on:
- postgres
- openldap
environment:
- DB_VENDOR=POSTGRES
- KEYCLOAK_USER=keycloak
- KEYCLOAK_PASSWORD=password
- KEYCLOAK_LOGLEVEL=DEBUG
- DB_VENDOR=POSTGRES
- DB_ADDR=postgres
- DB_PORT=5432
- DB_USER=keycloak
- DB_DATABASE=keycloak
- DB_PASSWORD=password
- KEYCLOAK_USER=keycloak
- KEYCLOAK_PASSWORD=password
- POSTGRES_PORT_5432_TCP_ADDR=postgres
- POSTGRES_PORT_5432_TCP_PORT=5432
ports:
- 8080:8080
volumes:
Expand Down
22 changes: 20 additions & 2 deletions docs/resources/keycloak_realm.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ resource "keycloak_realm" "realm" {
login_theme = "base"
access_code_lifespan = "1h"
ssl_required = "external"
password_policy = "upperCase(1) and length(8) and forceExpiredPasswordChange(365) and notUsername"
attributes = {
mycustomAttribute = "myCustomValue"
}
smtp_server {
host = "smtp.example.com"
Expand Down Expand Up @@ -46,6 +51,15 @@ resource "keycloak_realm" "realm" {
x_xss_protection = "1; mode=block"
strict_transport_security = "max-age=31536000; includeSubDomains"
}
brute_force_detection {
permanent_lockout = false
max_login_failures = 30
wait_increment_seconds = 60
quick_login_check_milli_seconds = 1000
minimum_quick_login_wait_seconds = 60
max_failure_wait_seconds = 900
failure_reset_time_seconds = 43200
}
}
}
```
Expand All @@ -71,6 +85,7 @@ If any of these attributes are not specified, they will default to Keycloak's de
- `verify_email` - (Optional) When true, users are required to verify their email address after registration and after email address changes.
- `login_with_email_allowed` - (Optional) When true, users may log in with their email address.
- `duplicate_emails_allowed` - (Optional) When true, multiple users will be allowed to have the same email address. This attribute must be set to `false` if `login_with_email_allowed` is set to `true`.
- `ssl_required` - (Optional) Can be one of following values: 'none, 'external' or 'all'

##### Themes

Expand All @@ -86,7 +101,7 @@ If any of these attributes are not specified, they will default to Keycloak's de

The following attributes can be found in the "Tokens" tab within the realm settings.

- `refresh_token_max_reuse` - (Optional) Maximum number of times a refresh token can be reused before they are revoked. If unspecified, refresh tokens will only be revoked when a different token is used.
- `refresh_token_max_reuse` - (Optional) Maximum number of times a refresh token can be reused before they are revoked. If unspecified, refresh tokens can be reused.

The attributes below should be specified as [Go duration strings](https://golang.org/pkg/time/#Duration.String). They will default to Keycloak's default settings.

Expand Down Expand Up @@ -129,7 +144,10 @@ Internationalization support can be configured by using the `internationalizatio

##### Security Defenses Headers

Header configuration support for browser security settings.
Header configuration support for browser security settings and brute force detection

#### Atributes
Map, can be used to add custom attributes to a realm. Or perhaps influence a certain attribute that is not supported in this terraform-provider

### Import

Expand Down
14 changes: 14 additions & 0 deletions example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,23 @@ resource "keycloak_realm" "test" {
x_xss_protection = "1; mode=block"
strict_transport_security = "max-age=31536000; includeSubDomains"
}

brute_force_detection {
permanent_lockout = false
max_login_failures = 31
wait_increment_seconds = 61
quick_login_check_milli_seconds = 1000
minimum_quick_login_wait_seconds = 120
max_failure_wait_seconds = 900
failure_reset_time_seconds = 43200
}
}

ssl_required = "external"
password_policy = "upperCase(1) and length(8) and forceExpiredPasswordChange(365) and notUsername"
attributes = {
mycustomAttribute = "myCustomValue"
}
}

resource "keycloak_required_action" "custom-terms-and-conditions" {
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ require (
)

replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999

go 1.13
52 changes: 34 additions & 18 deletions keycloak/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ type Realm struct {
DisplayName string `json:"displayName"`

// Login Config
RegistrationAllowed bool `json:"registrationAllowed"`
RegistrationEmailAsUsername bool `json:"registrationEmailAsUsername"`
EditUsernameAllowed bool `json:"editUsernameAllowed"`
ResetPasswordAllowed bool `json:"resetPasswordAllowed"`
RememberMe bool `json:"rememberMe"`
VerifyEmail bool `json:"verifyEmail"`
LoginWithEmailAllowed bool `json:"loginWithEmailAllowed"`
DuplicateEmailsAllowed bool `json:"duplicateEmailsAllowed"`
RegistrationAllowed bool `json:"registrationAllowed"`
RegistrationEmailAsUsername bool `json:"registrationEmailAsUsername"`
EditUsernameAllowed bool `json:"editUsernameAllowed"`
ResetPasswordAllowed bool `json:"resetPasswordAllowed"`
RememberMe bool `json:"rememberMe"`
VerifyEmail bool `json:"verifyEmail"`
LoginWithEmailAllowed bool `json:"loginWithEmailAllowed"`
DuplicateEmailsAllowed bool `json:"duplicateEmailsAllowed"`
SslRequired string `json:"sslRequired"`

//SMTP Server
SmtpServer SmtpServer `json:"smtpServer"`
Expand Down Expand Up @@ -65,8 +66,19 @@ type Realm struct {
SupportLocales []string `json:"supportedLocales"`
DefaultLocale string `json:"defaultLocale"`

//extra attributes of a realm, contains security defenses browser headers and brute force detection parameters(those still nee to be added)
Attributes Attributes `json:"attributes,omitempty"`
//extra attributes of a realm
Attributes map[string]interface{} `json:"attributes"`

BrowserSecurityHeaders BrowserSecurityHeaders `json:"browserSecurityHeaders"`

BruteForceProtected bool `json:"bruteForceProtected"`
PermanentLockout bool `json:"permanentLockout"`
FailureFactor int `json:"failureFactor"` //Max Login Failures
WaitIncrementSeconds int `json:"waitIncrementSeconds"`
QuickLoginCheckMilliSeconds int `json:"quickLoginCheckMilliSeconds"`
MinimumQuickLoginWaitSeconds int `json:"minimumQuickLoginWaitSeconds"`
MaxFailureWaitSeconds int `json:"maxFailureWaitSeconds"` //Max Wait
MaxDeltaTimeSeconds int `json:"maxDeltaTimeSeconds"` //Failure Reset Time

PasswordPolicy string `json:"passwordPolicy"`

Expand All @@ -79,14 +91,14 @@ type Realm struct {
DockerAuthenticationFlow string `json:"dockerAuthenticationFlow,omitempty"`
}

type Attributes struct {
BrowserHeaderContentSecurityPolicy string `json:"_browser_header.contentSecurityPolicy,omitempty"`
BrowserHeaderContentSecurityPolicyReportOnly string `json:"_browser_header.contentSecurityPolicyReportOnly,omitempty"`
BrowserHeaderStrictTransportSecurity string `json:"_browser_header.strictTransportSecurity,omitempty"`
BrowserHeaderXContentTypeOptions string `json:"_browser_header.xContentTypeOptions,omitempty"`
BrowserHeaderXFrameOptions string `json:"_browser_header.xFrameOptions,omitempty"`
BrowserHeaderXRobotsTag string `json:"_browser_header.xRobotsTag,omitempty"`
BrowserHeaderXXSSProtection string `json:"_browser_header.xXSSProtection,omitempty"`
type BrowserSecurityHeaders struct {
ContentSecurityPolicy string `json:"contentSecurityPolicy"`
ContentSecurityPolicyReportOnly string `json:"contentSecurityPolicyReportOnly"`
StrictTransportSecurity string `json:"strictTransportSecurity"`
XContentTypeOptions string `json:"xContentTypeOptions"`
XFrameOptions string `json:"xFrameOptions"`
XRobotsTag string `json:"xRobotsTag"`
XXSSProtection string `json:"xXSSProtection"`
}

type SmtpServer struct {
Expand Down Expand Up @@ -158,6 +170,10 @@ func (keycloakClient *KeycloakClient) ValidateRealm(realm *Realm) error {
return fmt.Errorf("validation error: DuplicateEmailsAllowed cannot be true if LoginWithEmailAllowed is true")
}

if realm.SslRequired != "none" && realm.SslRequired != "external" && realm.SslRequired != "all" {
return fmt.Errorf("validation error: SslRequired should be 'none', 'external' or 'all'")
}

// validate if the given theme exists on the server. the keycloak API allows you to use any random string for a theme
serverInfo, err := keycloakClient.GetServerInfo()
if err != nil {
Expand Down
Loading

0 comments on commit 340823e

Please sign in to comment.