diff --git a/Makefile b/Makefile index 0c4ab8d..07fcf64 100644 --- a/Makefile +++ b/Makefile @@ -149,6 +149,7 @@ tools: @which $(TFPROVIDERLINT) || go install github.com/bflad/tfproviderlint/cmd/tfproviderlint docs: build + go generate go run ./iamtf-docs/iamtf-docs.go "$(CURDIR)/reference/.tmp" "$(CURDIR)/reference" diff --git a/docs/doc_utils.go b/docs/doc_utils.go deleted file mode 100644 index 46009c3..0000000 --- a/docs/doc_utils.go +++ /dev/null @@ -1,370 +0,0 @@ -package docs - -import ( - "bufio" - "fmt" - "io/ioutil" - "os" - "sort" - "strings" - - "github.com/atricore/terraform-provider-iamtf/iamtf" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/pkg/errors" -) - -type GenContext struct { - out string - src string -} - -var CTX GenContext - -var IGNORE_PROPS = [...]string{"element_id"} - -// Generates documentation markdonw files in the destination path -func GenerateDocs(out string, src string) error { - - CTX = GenContext{ - out: out, - src: src, - } - - var errWrap error - - fmt.Print("Generating docs ... \n") - fmt.Printf("SRC: %s\n", CTX.src) - fmt.Printf("OUT: %s\n", CTX.out) - - err := initOut(CTX.out) - if err != nil { - errWrap = errors.Wrap(err, "init out") - } - - // 1. Provider documentation - err = genProvider("iamtf", iamtf.Provider()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf") - } - - // 2. Identity Appliance - err = genResource("iamtf_identity_appliance", iamtf.ResourceIdentityAppliance()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_identity_appliance out") - } - - // 3. Identity Provider - err = genResource("iamtf_idp", iamtf.ResourceIdP()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idp") - } - - err = genResource("iamtf_idp_facebook", iamtf.ResourceIdFacebook()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idp_facebook") - } - err = genResource("iamtf_idp_google", iamtf.ResourceidGoogle()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idp_google") - } - err = genResource("iamtf_idp_azure", iamtf.ResourceidAzure()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idp_azure") - } - - // 4. Identity Sources/Vaults - err = genResource("iamtf_idsource_db", iamtf.ResourcedbidSource()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idsource_db") - } - err = genResource("iamtf_idsource_ldap", iamtf.ResourceIdSourceLdap()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idsource_ldap") - } - err = genResource("iamtf_idvault", iamtf.ResourceIdVault()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_idvault") - } - - // 5. Applications - err = genResource("iamtf_app_agent", iamtf.ResourceJosso1Re()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_app_agent") - } - err = genResource("iamtf_app_oidc", iamtf.ResourceOidcRp()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_app_oidc") - } - err = genResource("iamtf_app_saml2", iamtf.ResourceExtSaml2Sp()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_app_saml2") - } - err = genResource("iamtf_app_sharepoint", iamtf.ResourceSharePoint()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_app_sharepoint") - } - - // 6. Execution Environments - err = genResource("iamtf_execenv_tomcat", iamtf.ResourceTomcatExecenv()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_execenv_tomcat") - } - err = genResource("iamtf_execenv_iis", iamtf.ResourceTomcatExecenv()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_execenv_iist") - } - err = genResource("iamtf_execenv_php", iamtf.ResourceTomcatExecenv()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_execenv_php") - } - err = genResource("iamtf_execenv_weblogic", iamtf.ResourceTomcatExecenv()) - if err != nil { - errWrap = errors.Wrap(err, "iamtf_execenv_weblogic") - } - - return errWrap -} - -func genProvider(name string, p *schema.Provider) error { - - return genDocs(name, "", p.Schema) - -} - -func genResource(name string, r *schema.Resource) error { - return genDocs(name, r.Description, r.Schema) -} - -func genDocs(name string, description string, m map[string]*schema.Schema) error { - - var errWrap error - - // Open writer - w, err := buildWriter(CTX.out, name) - if err != nil { - return err - } - - // Write header - err = printHeader("", name, w, 1) - if err != nil { - errWrap = errors.Wrap(err, "header") - } - fmt.Fprintf(w, "\n%s\n\n", description) - - // Write properties - f := func(p string, n string, s *schema.Schema, depth int) error { - err = printProperty(p, n, s, w, depth) - if err != nil { - errWrap = errors.Wrap(err, "property") - } - return nil - } - - // Process children - err = walkSchemaMap("", name, m, f, 2) - if err != nil { - errWrap = errors.Wrap(err, "walker") - } - - // Print footer - err = printFooter("", name, w, 1) - if err != nil { - errWrap = errors.Wrap(err, "footer") - } - w.Flush() - - return errWrap - -} - -func printHeader(path string, name string, w *bufio.Writer, depth int) error { - - for i := 0; i < depth; i++ { - fmt.Fprint(w, "#") - } - fmt.Fprintf(w, " %s\n", name) - - // Add manual documentation - copyContent(fmt.Sprintf("%s/%s_%s_h.md", CTX.src, path, name), w) - - return nil -} - -func printFooter(path string, name string, w *bufio.Writer, depth int) error { - - // Add manual documentation - fmt.Fprint(w, "\n") - copyContent(fmt.Sprintf("%s/%s_%s_f.md", CTX.src, path, name), w) - fmt.Fprint(w, "\n") - - return nil -} - -func printBody(path string, name string, s *schema.Schema, w *bufio.Writer, depth int) error { - fmt.Fprintf(w, "\n%s\n\n", s.Description) - - copyContent(fmt.Sprintf("%s/%s_%s_b.md", CTX.src, path, name), w) - - fmt.Fprintf(w, "* type: %s\n", strings.TrimPrefix(s.Type.String(), "Type")) - - if s.Required { - fmt.Fprintf(w, "* required") - } - if s.Optional { - fmt.Fprintf(w, "* optional: %t\n", s.Optional) - } - - if s.Computed { - fmt.Fprintf(w, "* computed: %t\n", s.Computed) - } - - fmt.Fprintf(w, "\n") - - return nil -} - -// Prints the schema property definition. -func printProperty(p string, n string, s *schema.Schema, w *bufio.Writer, depth int) error { - - var errWrap error - - // TODO : errors! - err := printHeader(p, n, w, depth) - if err != nil { - errWrap = errors.Wrap(err, "header") - } - - err = printBody(p, n, s, w, depth) - if err != nil { - errWrap = errors.Wrap(err, "body") - } - - err = printFooter(p, n, w, depth) - if err != nil { - errWrap = errors.Wrap(err, "footer") - } - - return errWrap -} - -// -// This walks an element by exuting the provided function on all its children -// -// ns : namespace of the element to process -// name : of the element to process -func walkSchemaMap( - ns string, - name string, - props map[string]*schema.Schema, - fn func(ns string, name string, sc *schema.Schema, depth int) error, depth int) error { - - keys := keys(props) - sort.Strings(keys) - // Get keys from map, each key is a property - for _, prop_name := range keys { - - if isIgnored(prop_name) { - continue - } - - prop_value := props[prop_name] - prop_ns := fmt.Sprintf("%s_%s", ns, name) - - // Cal the function that handles the prop - err := fn(prop_ns, prop_name, prop_value, depth) - if err != nil { - return err - } - - // If the prop is a list, walk its children - switch prop_value.Type { - case schema.TypeList: - o := prop_value.Elem - if r, ok := o.(*schema.Resource); ok { - err = walkSchemaMap(prop_ns, prop_name, r.Schema, fn, depth+1) - if err != nil { - return err - } - } - case schema.TypeMap: - // TODO ! - case schema.TypeSet: - // TODO ! - } - - } - return nil - -} - -func isIgnored(p string) bool { - for _, i := range IGNORE_PROPS { - if i == p { - return true - } - } - return false -} - -func keys(m map[string]*schema.Schema) []string { - keys := make([]string, len(m)) - - i := 0 - for k := range m { - keys[i] = k - i++ - } - - sort.Strings(keys) - - return keys -} - -func buildWriter(path string, name string) (*bufio.Writer, error) { - var f *os.File - var err error - var writer *bufio.Writer - fname := fmt.Sprintf("%s/%s.md", path, name) - - // change to either true|false - outputToScreen := false - if outputToScreen { - f = os.Stdout - } else { - f, err = os.OpenFile(fname, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return writer, fmt.Errorf("Error opening file %s: %v", fname, err) - } - } - - return bufio.NewWriter(f), nil - -} - -func initOut(dname string) error { - if _, err := os.Stat(dname); errors.Is(err, os.ErrNotExist) { - err := os.Mkdir(dname, os.ModePerm) - if err != nil { - return err - } - } - return nil -} - -// If file does not exists, ignore it -func copyContent(fname string, w *bufio.Writer) error { - // open input file - - src, err := ioutil.ReadFile(fname) - if err != nil { - // If file not found , ignore and return - if errors.Is(err, os.ErrNotExist) { - return nil - } - return err - } - _, err = w.Write(src) - - return err -} diff --git a/docs/doc_utils_test.go b/docs/doc_utils_test.go deleted file mode 100644 index 09241bd..0000000 --- a/docs/doc_utils_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package docs - -import "testing" - -func TestDocs(t *testing.T) { - - err := GenerateDocs("../.tmp", "../reference") - if err != nil { - t.Error(err) - } - -} diff --git a/docs/resources/identity_appliance.md b/docs/resources/identity_appliance.md index 2d77e79..7f865cd 100644 --- a/docs/resources/identity_appliance.md +++ b/docs/resources/identity_appliance.md @@ -12,50 +12,6 @@ description: |- -The following is an example of an identity appliance definition. The resource **name** and name property must match. The **namespace** must be unique in the server and follow java package naming convention. (use characters and dots). The **location** is the base public URL to access all the services. - -``` -resource "iamtf_identity_appliance" "my-ida" { - name = "my-ida" - namespace = "com.mycompany.myida" - description = "My identity appliance!" - location = "https://mysso.mycompany.com" -} - -``` - -JOSSO will create all service URLs under the two paths: **/IDBUS** and **/IDBUS-UI**. - -In our example, these are thebase locations: - -* https://mysso.mycompany.com/IDBUS/MY-IDA -* https://mysso.mycompany.com/IDBUS-UI/MY-IDA - -:::tip -You should configure your load balancer or reverse proxy to **ONLY forward requests using these paths to JOSSO servers**. -::: -The following is an example of an identity appliance definition. The resource **name** and name property must match. The **namespace** must be unique in the server and follow java package naming convention. (use characters and dots). The **location** is the base public URL to access all the services. - -``` -resource "iamtf_identity_appliance" "my-ida" { - name = "my-ida" - namespace = "com.mycompany.myida" - description = "My identity appliance!" - location = "https://mysso.mycompany.com" -} - -``` - -JOSSO will create all service URLs under the two paths: **/IDBUS** and **/IDBUS-UI**. - -In our example, these are thebase locations: - -* https://mysso.mycompany.com/IDBUS/MY-IDA -* https://mysso.mycompany.com/IDBUS-UI/MY-IDA - -:::tip -You should configure your load balancer or reverse proxy to **ONLY forward requests using these paths to JOSSO servers**. -::: The following is an example of an identity appliance definition. The resource **name** and name property must match. The **namespace** must be unique in the server and follow java package naming convention. (use characters and dots). The **location** is the base public URL to access all the services. ``` diff --git a/docs/resources/idp.md b/docs/resources/idp.md index f877a37..43872ea 100644 --- a/docs/resources/idp.md +++ b/docs/resources/idp.md @@ -12,92 +12,6 @@ description: |- -This is one of the key resources available in JOSSO. It allows you to define an identity provider. JOSSO supports multiple identity protocols, you can connect any SP using: - -* OpenID Connect 1.0 -* OAuth 2.0 -* SAML 2.0 -* JOSSO 1.0 -* Custom - -You can mix heterogeneouse service providers that have different requireminets and connect them with a single IDP. For example, you can share identity between SAML and OIDC applications transparently, providing users with a single authentication experience. - -To configure an IDP you must provide an **identity source**, an **authentication mechanism** and a **keystore**. Then you need to define each **service provider**, and reference the trusted IDP. - -In JOSSO you can have multiple identity providers running in a single identity appliance. - -Let's take a look at the following example: - -``` -resource "iamtf_idp" "idp" { - - ida = iamtf_identity_appliance.ida-1.name - - name = "idp" - - keystore { - resource = filebase64("./idp.p12") - password = "changeme" - } - - id_sources = [iamtf_idvault.sso-users.name] - - authn_basic { - priority = 0 - pwd_hash = "SHA-256" - pwd_encoding = "BASE64" - } - - depends_on = [ - iamtf_idvault.sso-users - ] - -} -``` - -This is one of the key resources available in JOSSO. It allows you to define an identity provider. JOSSO supports multiple identity protocols, you can connect any SP using: - -* OpenID Connect 1.0 -* OAuth 2.0 -* SAML 2.0 -* JOSSO 1.0 -* Custom - -You can mix heterogeneouse service providers that have different requireminets and connect them with a single IDP. For example, you can share identity between SAML and OIDC applications transparently, providing users with a single authentication experience. - -To configure an IDP you must provide an **identity source**, an **authentication mechanism** and a **keystore**. Then you need to define each **service provider**, and reference the trusted IDP. - -In JOSSO you can have multiple identity providers running in a single identity appliance. - -Let's take a look at the following example: - -``` -resource "iamtf_idp" "idp" { - - ida = iamtf_identity_appliance.ida-1.name - - name = "idp" - - keystore { - resource = filebase64("./idp.p12") - password = "changeme" - } - - id_sources = [iamtf_idvault.sso-users.name] - - authn_basic { - priority = 0 - pwd_hash = "SHA-256" - pwd_encoding = "BASE64" - } - - depends_on = [ - iamtf_idvault.sso-users - ] - -} -``` - This is one of the key resources available in JOSSO. It allows you to define an identity provider. JOSSO supports multiple identity protocols, you can connect any SP using: * OpenID Connect 1.0