Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

brute-force-detection-settings + ssl_required + custom-realm-attributes + fix 174 + k8.0.0 #183

Merged
Show file tree
Hide file tree
Changes from 4 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
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
23 changes: 21 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,8 @@ 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.
- `revoke_refresh_token` - (Optional) If enabled a refresh token can only be used number of times specified in 'refresh_token_max_reuse' before they are revoked. If unspecified, refresh tokens can be reused.
- `refresh_token_max_reuse` - (Optional) Maximum number of times a refresh token can be reused before they are revoked. If unspecified and 'revoke_refresh_token' is enabled the default value is 0 and refresh tokens can not 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 +145,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
15 changes: 14 additions & 1 deletion example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ resource "keycloak_realm" "test" {
}

account_theme = "base"

access_code_lifespan = "30m"

internationalization {
Expand All @@ -50,9 +49,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
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ require (
github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 // indirect
github.com/hashicorp/terraform v0.12.1
github.com/mitchellh/go-homedir v1.1.0 // indirect
golang.org/x/net v0.0.0-20190502183928-7f726cade0ab
)

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

go 1.13
56 changes: 36 additions & 20 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,omitempty"`

//SMTP Server
SmtpServer SmtpServer `json:"smtpServer"`
Expand All @@ -46,8 +47,8 @@ type Realm struct {
EmailTheme string `json:"emailTheme,omitempty"`

// Tokens
RevokeRefreshToken bool `json:"revokeRefreshToken,omitempty"`
RefreshTokenMaxReuse int `json:"refreshTokenMaxReuse,omitempty"`
RevokeRefreshToken bool `json:"revokeRefreshToken"`
RefreshTokenMaxReuse int `json:"refreshTokenMaxReuse"`
SsoSessionIdleTimeout int `json:"ssoSessionIdleTimeout,omitempty"`
SsoSessionMaxLifespan int `json:"ssoSessionMaxLifespan,omitempty"`
OfflineSessionIdleTimeout int `json:"offlineSessionIdleTimeout,omitempty"`
Expand All @@ -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"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a breaking change in Keycloak's API? It looks like we were using _browser_header before - is that going to break this provider's compatibility with older versions of Keycloak?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Realm tests stills work if I run on ac test with 'make local' and docker-compose pointing to keycloak version 4.8.3.Final
There 2 ways of setting these parameters, The UI is using the way above
I have no idea why there are 2 ways to do this. If you set both ways at the same time with different values, then setting it directly as a real parameters wins from setting it through the attributes.
Thus this seems to be the safer bet and a more correct way to do it through this method.


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