Browse Source

support custom templates

main
Nicolas Massé 5 years ago
parent
commit
1d591491c8
  1. 25
      cli/cmd/generate.go
  2. 319
      examples/custom-with-ldap.template
  3. 20
      generate.go

25
cli/cmd/generate.go

@ -20,15 +20,17 @@ package cmd
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path" "path"
"text/template"
kcimport "github.com/nmasse-itix/keycloak-realm-import" kcimport "github.com/nmasse-itix/keycloak-realm-import"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var realmCount, clientCount, userCount int var realmCount, clientCount, userCount int
var targetDir string var targetDir, customTemplateFile string
// generateCmd represents the generate command // generateCmd represents the generate command
var generateCmd = &cobra.Command{ var generateCmd = &cobra.Command{
@ -40,14 +42,32 @@ var generateCmd = &cobra.Command{
if err != nil { if err != nil {
logger.Fatal(err) logger.Fatal(err)
} }
var customTemplate *template.Template
if customTemplateFile != "" {
b, err := ioutil.ReadFile(customTemplateFile)
if err != nil {
logger.Fatal(err)
}
content := string(b)
customTemplate, err = kcimport.GetRealmTemplate(content)
}
realms := kcimport.GenerateRealms(realmCount, clientCount, userCount) realms := kcimport.GenerateRealms(realmCount, clientCount, userCount)
for _, realm := range realms { for _, realm := range realms {
f, err := os.OpenFile(path.Join(targetDir, fmt.Sprintf("realm-%s.json", realm.ID)), os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666) f, err := os.OpenFile(path.Join(targetDir, fmt.Sprintf("realm-%s.json", realm.ID)), os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil { if err != nil {
logger.Fatal(err) logger.Fatal(err)
} }
defer f.Close() defer f.Close()
err = kcimport.WriteRealmFile(realm, f)
if customTemplate != nil {
err = kcimport.WriteRealmFileWithTemplate(realm, f, customTemplate)
} else {
err = kcimport.WriteRealmFile(realm, f)
}
if err != nil { if err != nil {
logger.Fatal(err) logger.Fatal(err)
} }
@ -61,4 +81,5 @@ func init() {
generateCmd.Flags().IntVar(&clientCount, "clients", 10, "number of clients to generate per realm") generateCmd.Flags().IntVar(&clientCount, "clients", 10, "number of clients to generate per realm")
generateCmd.Flags().IntVar(&userCount, "users", 10, "number of users to generate per realm") generateCmd.Flags().IntVar(&userCount, "users", 10, "number of users to generate per realm")
generateCmd.Flags().StringVar(&targetDir, "target", ".", "target directory") generateCmd.Flags().StringVar(&targetDir, "target", ".", "target directory")
generateCmd.Flags().StringVar(&customTemplateFile, "template", "", "go template used to generate the realm")
} }

319
examples/custom-with-ldap.template

@ -0,0 +1,319 @@
{
"id": "realm_{{ .ID }}",
"realm": "realm_{{ .ID }}",
"displayName": "realm_{{ .ID }}",
"notBefore": 0,
"revokeRefreshToken": false,
"refreshTokenMaxReuse": 0,
"accessTokenLifespan": 300,
"accessTokenLifespanForImplicitFlow": 900,
"ssoSessionIdleTimeout": 1800,
"ssoSessionMaxLifespan": 36000,
"offlineSessionIdleTimeout": 2592000,
"accessCodeLifespan": 60,
"accessCodeLifespanUserAction": 300,
"accessCodeLifespanLogin": 1800,
"actionTokenGeneratedByAdminLifespan": 43200,
"actionTokenGeneratedByUserLifespan": 300,
"enabled": true,
"sslRequired": "external",
"registrationAllowed": false,
"registrationEmailAsUsername": false,
"rememberMe": false,
"verifyEmail": false,
"loginWithEmailAllowed": true,
"duplicateEmailsAllowed": false,
"resetPasswordAllowed": false,
"editUsernameAllowed": false,
"bruteForceProtected": false,
"permanentLockout": false,
"maxFailureWaitSeconds": 900,
"minimumQuickLoginWaitSeconds": 60,
"waitIncrementSeconds": 60,
"quickLoginCheckMilliSeconds": 1000,
"maxDeltaTimeSeconds": 43200,
"failureFactor": 30,
"users": [
{{- range $count, $user := .Users }}
{{- if gt $count 0 }},{{ end }}
{
"username": "user_{{ $user.ID }}",
"firstName": "User",
"lastName": "{{ $user.ID }}",
"email": "user_{{ $user.ID }}@nowhere.test",
"emailVerified": true,
"enabled": true,
"credentials": [
{
"type": "password",
"value": "user_{{ $user.ID }}"
}
],
"requiredActions": [],
"realmRoles": [],
"applicationRoles": {}
}
{{- end }}
],
"roles": {
"realm": [],
"client": {}
},
"defaultRoles": [],
"requiredCredentials": [ "password" ],
"scopeMappings": [],
"clientScopeMappings": {},
"clients": [
{{- range $count, $client := .Clients }}
{{- if gt $count 0 }},{{ end }}
{
"clientId": "app_{{ $client.ID }}",
"name": "app_{{ $client.ID }}",
"enabled": true,
"publicClient": false,
"redirectUris": [
"http://dummy/url"
],
"fullScopeAllowed": false,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": true,
"clientAuthenticatorType": "client-secret",
"secret": "{{ $client.Secret }}"
}
{{- end }}
],
"components": {
"org.keycloak.storage.UserStorageProvider": [
{
"name": "ldap",
"providerId": "ldap",
"subComponents": {
"org.keycloak.storage.ldap.mappers.LDAPStorageMapper": [
{
"name": "modify date",
"providerId": "user-attribute-ldap-mapper",
"subComponents": {},
"config": {
"ldap.attribute": [
"modifyTimestamp"
],
"is.mandatory.in.ldap": [
"false"
],
"always.read.value.from.ldap": [
"true"
],
"read.only": [
"true"
],
"user.model.attribute": [
"modifyTimestamp"
]
}
},
{
"name": "username",
"providerId": "user-attribute-ldap-mapper",
"subComponents": {},
"config": {
"ldap.attribute": [
"uid"
],
"is.mandatory.in.ldap": [
"true"
],
"read.only": [
"true"
],
"always.read.value.from.ldap": [
"false"
],
"user.model.attribute": [
"username"
]
}
},
{
"name": "first name",
"providerId": "user-attribute-ldap-mapper",
"subComponents": {},
"config": {
"ldap.attribute": [
"cn"
],
"is.mandatory.in.ldap": [
"true"
],
"read.only": [
"true"
],
"always.read.value.from.ldap": [
"true"
],
"user.model.attribute": [
"firstName"
]
}
},
{
"name": "email",
"providerId": "user-attribute-ldap-mapper",
"subComponents": {},
"config": {
"ldap.attribute": [
"mail"
],
"is.mandatory.in.ldap": [
"false"
],
"always.read.value.from.ldap": [
"false"
],
"read.only": [
"true"
],
"user.model.attribute": [
"email"
]
}
},
{
"name": "last name",
"providerId": "user-attribute-ldap-mapper",
"subComponents": {},
"config": {
"ldap.attribute": [
"sn"
],
"is.mandatory.in.ldap": [
"true"
],
"always.read.value.from.ldap": [
"true"
],
"read.only": [
"true"
],
"user.model.attribute": [
"lastName"
]
}
},
{
"name": "creation date",
"providerId": "user-attribute-ldap-mapper",
"subComponents": {},
"config": {
"ldap.attribute": [
"createTimestamp"
],
"is.mandatory.in.ldap": [
"false"
],
"always.read.value.from.ldap": [
"true"
],
"read.only": [
"true"
],
"user.model.attribute": [
"createTimestamp"
]
}
}
]
},
"config": {
"pagination": [
"true"
],
"fullSyncPeriod": [
"-1"
],
"usersDn": [
"ou=users,dc=keycloak,dc=org"
],
"connectionPooling": [
"true"
],
"cachePolicy": [
"DEFAULT"
],
"useKerberosForPasswordAuthentication": [
"false"
],
"importEnabled": [
"true"
],
"enabled": [
"true"
],
"bindCredential": [
"keycloak"
],
"bindDn": [
"cn=admin,dc=keycloak,dc=org"
],
"changedSyncPeriod": [
"-1"
],
"usernameLDAPAttribute": [
"uid"
],
"lastSync": [
"1611161804"
],
"vendor": [
"other"
],
"uuidLDAPAttribute": [
"entryUUID"
],
"connectionUrl": [
"ldap://openldap.dns.podman:389/"
],
"allowKerberosAuthentication": [
"false"
],
"syncRegistrations": [
"false"
],
"authType": [
"simple"
],
"debug": [
"false"
],
"searchScope": [
"1"
],
"useTruststoreSpi": [
"ldapsOnly"
],
"priority": [
"0"
],
"trustEmail": [
"true"
],
"userObjectClasses": [
"inetOrgPerson, organizationalPerson"
],
"rdnLDAPAttribute": [
"uid"
],
"editMode": [
"READ_ONLY"
],
"validatePasswordPolicy": [
"false"
],
"batchSizeForSync": [
"1000"
]
}
}
]
}
}

20
generate.go

@ -57,7 +57,7 @@ func init() {
fmt.Printf("init: %s\n", err) fmt.Printf("init: %s\n", err)
} }
defaultTemplate, err = getTemplate(statikFS, "/realm.template", "realm") defaultTemplate, err = getTemplate(statikFS, "/realm.template")
if err != nil { if err != nil {
fmt.Printf("init: %s\n", err) fmt.Printf("init: %s\n", err)
} }
@ -100,31 +100,25 @@ func WriteRealmFile(realm GeneratedRealm, out io.Writer) error {
return WriteRealmFileWithTemplate(realm, out, defaultTemplate) return WriteRealmFileWithTemplate(realm, out, defaultTemplate)
} }
func getTemplate(statikFS http.FileSystem, filename string, name string) (*template.Template, error) { func GetRealmTemplate(content string) (*template.Template, error) {
tmpl := template.New(name) tmpl := template.New("realm")
content, err := slurpFile(statikFS, filename)
if err != nil {
return nil, err
}
customFunctions := template.FuncMap{ customFunctions := template.FuncMap{
// TODO // TODO
} }
return tmpl.Funcs(customFunctions).Parse(content) return tmpl.Funcs(customFunctions).Parse(content)
} }
func slurpFile(statikFS http.FileSystem, filename string) (string, error) { func getTemplate(statikFS http.FileSystem, filename string) (*template.Template, error) {
fd, err := statikFS.Open(filename) fd, err := statikFS.Open(filename)
if err != nil { if err != nil {
return "", err return nil, err
} }
defer fd.Close() defer fd.Close()
content, err := ioutil.ReadAll(fd) content, err := ioutil.ReadAll(fd)
if err != nil { if err != nil {
return "", err return nil, err
} }
return string(content), nil return GetRealmTemplate(string(content))
} }

Loading…
Cancel
Save