diff --git a/CHANGELOG.md b/CHANGELOG.md index 252d990..44e742c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.8.0] - 2019-05-01 + +### Added +- Modules to manage + - [WAF](https://docs.cloud.oracle.com/iaas/Content/WAF/Concepts/overview.htm) + - [Federation](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/federation.htm) +- Added the following features in existing modules: + - New allowed values `approximateSize` and `approximateCount` for the `fields` parameter of `oci_bucket_facts` module. These enable populating `approximate_size` and `approximate_count` in the response. +- Samples to demonstrate: + - how to a launch compute instance using an app catalog image + +### Changed +- Minimum supported OCI Python SDK to `2.1.7` + ## [1.7.0] - 2019-04-01 ### Added diff --git a/README.md b/README.md index 9b22003..67ea1b4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Oracle Cloud Infrastructure Ansible Modules provide an easy way to create and pr - Compute - Container Engine for Kubernetes Service (OKE) - Database (including support for Autonomous Transaction Processing and Autonomous Data Warehouse Services) -- Domain Name System (DNS) +- Edge Services (DNS, WAF) - IAM - Load Balancing - Networking @@ -33,7 +33,7 @@ This project includes a catalog of Oracle Cloud Infrastructure Ansible module sa - Compute - Container Engine for Kubernetes Service (OKE) - Database (including support for Autonomous Transaction Processing and Autonomous Data Warehouse Services) -- Domain Name System (DNS) +- Edge Services (DNS) - IAM - Load Balancing - Networking diff --git a/docs/modules/list_of_cloud_modules.rst b/docs/modules/list_of_cloud_modules.rst index 2296386..9902879 100644 --- a/docs/modules/list_of_cloud_modules.rst +++ b/docs/modules/list_of_cloud_modules.rst @@ -96,6 +96,10 @@ Oracle * :ref:`oci_file_system_facts_module` * :ref:`oci_group_module` * :ref:`oci_group_facts_module` + * :ref:`oci_identity_provider_module` + * :ref:`oci_identity_provider_facts_module` + * :ref:`oci_idp_group_mapping_module` + * :ref:`oci_idp_group_mapping_facts_module` * :ref:`oci_image_module` * :ref:`oci_image_facts_module` * :ref:`oci_instance_module` @@ -222,6 +226,14 @@ Oracle * :ref:`oci_volume_group_backup_module` * :ref:`oci_volume_group_backup_facts_module` * :ref:`oci_volume_group_facts_module` + * :ref:`oci_waas_certificate_module` + * :ref:`oci_waas_certificate_facts_module` + * :ref:`oci_waas_edge_subnet_facts_module` + * :ref:`oci_waas_policy_module` + * :ref:`oci_waas_policy_facts_module` + * :ref:`oci_waas_recommendation_facts_module` + * :ref:`oci_waas_work_request_module` + * :ref:`oci_waas_work_request_facts_module` * :ref:`oci_zone_module` * :ref:`oci_zone_facts_module` * :ref:`oci_zone_records_module` diff --git a/docs/modules/oci_app_catalog_listing_resource_version_facts_module.rst b/docs/modules/oci_app_catalog_listing_resource_version_facts_module.rst index 24c9f5b..8fced4f 100644 --- a/docs/modules/oci_app_catalog_listing_resource_version_facts_module.rst +++ b/docs/modules/oci_app_catalog_listing_resource_version_facts_module.rst @@ -206,7 +206,7 @@ Common return values are documented :ref:`here `, the foll
List of resource versions for a particular listing

Sample:
-
[{'available_regions': ['us-ashburn-1', 'us-phoenix-1'], 'listing_resource_version': '1.0.0', 'allowed_actions': [], 'listing_id': 'ocid1.appcataloglisting.oc1..xxxxxEXAMPLExxxxx', 'accessible_ports': [], 'compatible_shapes': ['VM.Standard1.1', 'VM.Standard1.2'], 'listing_resource_id': 'ocid1.image.oc1..xxxxxEXAMPLExxxxx', 'time_published': '2019-02-14T19:53:30.878000+00:00'}]
+
[{'available_regions': ['us-ashburn-1', 'us-phoenix-1'], 'listing_resource_version': '1.0.0', 'allowed_actions': [], 'listing_id': 'ocid1.appcataloglisting.oc1..xxxxxEXAMPLExxxxx', 'accessible_ports': [], 'compatible_shapes': ['VM.Standard2.1', 'VM.Standard2.2'], 'listing_resource_id': 'ocid1.image.oc1..xxxxxEXAMPLExxxxx', 'time_published': '2019-02-14T19:53:30.878000+00:00'}]
@@ -286,7 +286,7 @@ Common return values are documented :ref:`here `, the foll
List of shapes compatible with this resource.

Sample:
-
['VM.Standard1.1', 'VM.Standard1.2']
+
['VM.Standard2.1', 'VM.Standard2.2']
diff --git a/docs/modules/oci_bucket_facts_module.rst b/docs/modules/oci_bucket_facts_module.rst index 05b593e..0259f49 100644 --- a/docs/modules/oci_bucket_facts_module.rst +++ b/docs/modules/oci_bucket_facts_module.rst @@ -101,7 +101,7 @@ Parameters -
Identifier of the compartment from which facts of constituent buckets needs to be fetched. Required to get details of all buckets in a specified namespace and compartment.
+
Identifier of the compartment from which facts of constituent buckets needs to be fetched. Required to get details of all buckets in a specified namespace and compartment.
@@ -131,10 +131,12 @@ Parameters -
Bucket summary in list of buckets includes the 'namespace', 'name', 'compartmentId', 'createdBy', 'timeCreated', and 'etag' fields. This parameter can also include 'tags' (freeformTags and definedTags). The only supported value of this parameter is 'tags' for now.
+
Specifies additional fields to be returned in the response. By default a response includes the 'namespace', 'name', 'compartment_id', 'created_by', 'time_created', and 'etag' fields. Specifying "tags" will populate the fields "freeform_tags" and "defined_tags". Specifying "approximateSize" will populate the field "approximate_size". Specifying "approximateCount" will populate the field "approximate_size". Any combination of the values may be provided.
@@ -204,12 +206,25 @@ Examples namespace_name: 'mynamespace' compartment_id: 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx' - #Fetch facts of a specific bucket + - name: List bucket facts (including tags) + oci_bucket_facts: + namespace_name: 'mynamespace' + compartment_id: 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx' + fields: ["tags"] + + # Fetch facts of a specific bucket - name: Fetch a bucket oci_bucket_facts: namespace_name: 'mynamespace' name: 'Bucket1' + # Fetch facts of a specific bucket (including approximate size and count) + - name: Fetch a bucket + oci_bucket_facts: + namespace_name: 'mynamespace' + name: 'Bucket1' + fields: ["approximateSize", "approximateCount"] + @@ -265,6 +280,18 @@ Common return values are documented :ref:`here `, the foll
Sample:
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+ + +   + + approximate_count +
int
+ + only when 'approximateCount' is specified in the 'fields' input option + +
The approximate number of objects in the bucket. Count statistics are reported periodically. You will see a lag between what is displayed and the actual object count.
+
+   @@ -335,6 +362,18 @@ Common return values are documented :ref:`here `, the foll
Sample:
NoPublicAccess
+ + +   + + approximate_size +
int
+ + only when 'approximateSize' is specified in the 'fields' input option + +
The approximate total size of all objects in the bucket. Size statistics are reported periodically. You will see a lag between what is displayed and the actual size of the bucket.
+
+   diff --git a/docs/modules/oci_identity_provider_facts_module.rst b/docs/modules/oci_identity_provider_facts_module.rst new file mode 100644 index 0000000..13bc25c --- /dev/null +++ b/docs/modules/oci_identity_provider_facts_module.rst @@ -0,0 +1,451 @@ +:source: cloud/oracle/oci_identity_provider_facts.py + +:orphan: + +.. _oci_identity_provider_facts_module: + + +oci_identity_provider_facts - Retrieve details about published App Catalog listings in OCI Compute Service +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module retrieves information of a specified app catalog listing or lists all the app catalog listings in the tenancy. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ compartment_id +
str
+ +
The OCID of the tenancy (remember that the tenancy is simply the root compartment).
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ identity_provider_id +
str
+ +
The OCID of the identity provider. Required to get information of a specific identity provider.
+

aliases: id
+
+ name +
str
+ +
Filter the identity providers with given name.
+
+ protocol +
str
+
    Choices: +
  • SAML2 ←
  • +
+
+
The protocol used for federation.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get all identity providers of given protocol in the tenancy + oci_identity_provider_facts: + protocol: SAML2 + compartment_id: ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx + + - name: Get a specific identity provider using its OCID + oci_identity_provider_facts: + identity_provider_id: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ identity_providers +
complex
+
on success +
List of identity provider details
+
+
Sample:
+
[{'lifecycle_state': 'ACTIVE', 'inactive_status': None, 'product_type': 'ADFS', 'description': 'Test Identity Provider', 'compartment_id': 'ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx', 'defined_tags': {}, 'freeform_tags': {}, 'signing_certificate': None, 'time_created': '2019-04-01T21:49:41.934000+00:00', 'redirect_url': 'https://testidp.oracletest.com/adfs/ls/', 'metadata_url': None, 'protocol': 'SAML2', 'freeform_attributes': {}, 'id': 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx', 'name': 'TEST_IDENTITY_PROVDER'}]
+
  + lifecycle_state +
str
+
success +
The current state. After creating an IdentityProvider, make sure its lifecycleState changes from CREATING to ACTIVE before using it.
+
+
Sample:
+
ACTIVE
+
  + inactive_status +
str
+
success +
The detailed status of INACTIVE lifecycleState.
+
+
  + product_type +
str
+
success +
The identity provider service or product. Supported identity providers are Oracle Identity Cloud Service (IDCS) and Microsoft Active Directory Federation Services (ADFS).
+
+
Sample:
+
ADFS
+
  + description +
str
+
success +
The description you assign to the IdentityProvider during creation.
+
+
Sample:
+
Test identity provider
+
  + compartment_id +
str
+
success +
The OCID of the tenancy containing the IdentityProvider.
+
+
Sample:
+
ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx
+
  + defined_tags +
str
+
success +
Defined tags for this resource. Each key is predefined and scoped to a namespace.
+
+
Sample:
+
{'Operations': {'CostCenter': '42'}}
+
  + freeform_tags +
str
+
success +
Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace.
+
+
Sample:
+
{'Department': 'Finance'}
+
  + signing_certificate +
str
+
success +
The identity provider's signing certificate used by the IAM Service to validate the SAML2 token.
+
+
  + time_created +
str
+
success +
Date and time the IdentityProvider was created, in the format defined by RFC3339.
+
+
Sample:
+
2016-08-25 21:10:29.600000
+
  + redirect_url +
str
+
success +
The URL to redirect federated users to for authentication with the identity provider.
+
+
Sample:
+
https://idpinstance.ansibletest.com/adfs/ls/
+
  + metadata_url +
str
+
success +
The URL for retrieving the identity provider's metadata, which contains information required for federating.
+
+
Sample:
+
https://idcs-31ddf5c2bxxxxxxx429d5c2c927.identity.oraclecloud.com
+
  + protocol +
str
+
success +
The protocol used for federation.
+
+
Sample:
+
SAML2
+
  + id +
str
+
success +
The OCID of the IdentityProvider.
+
+
Sample:
+
ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx
+
  + name +
str
+
success +
The name you assign to the IdentityProvider during creation. The name must be unique across all IdentityProvider objects in the tenancy and cannot be changed. This is the name federated users see when choosing which identity provider to use when signing in to the Oracle Cloud Infrastructure Console.
+
+
Sample:
+
TEST_IDENTITY_PROVDER
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_identity_provider_module.rst b/docs/modules/oci_identity_provider_module.rst new file mode 100644 index 0000000..b69a0a0 --- /dev/null +++ b/docs/modules/oci_identity_provider_module.rst @@ -0,0 +1,417 @@ +:source: cloud/oracle/oci_identity_provider.py + +:orphan: + +.. _oci_identity_provider_module: + + +oci_identity_provider - Manage Identity Providers in OCI +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module allows the user to create, delete and update identity providers in OCI. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ compartment_id +
str
+ +
The OCID of your tenancy.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ defined_tags + + +
Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/resourcetags.htm.
+
+ description +
str
+ +
The description you assign to the IdentityProvider during creation. Does not have to be unique, and it's changeable.
+
+ force_create +
bool
+
    Choices: +
  • no ←
  • +
  • yes
  • +
+
+
Whether to attempt non-idempotent creation of a resource. By default, create resource is an idempotent operation, and doesn't create the resource if it already exists. Setting this option to true, forcefully creates a copy of the resource, even if it already exists.This option is mutually exclusive with key_by.
+
+ freeform_attributes +
dict
+ +
Extra name value pairs associated with this identity provider.
+
+ freeform_tags + + +
Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/resourcetags.htm.
+
+ identity_provider_id +
str
+ +
The OCID of the identity provider. Required when deleting the identity provider with state=absent or updating the identity provider with state=present. This option is mutually exclusive with compartment_id.
+

aliases: id
+
+ key_by + + +
The list of comma-separated attributes of this resource which should be used to uniquely identify an instance of the resource. By default, all the attributes of a resource except freeform_tags are used to uniquely identify a resource.
+
+ metadata +
str
+ +
The XML that contains the information required for federating.
+
+ metadata_url +
str
+ +
The URL for retrieving the identity provider's metadata, which contains information required for federating.
+
+ name +
str
+ +
The name you assign to the IdentityProvider during creation. The name must be unique across all IdentityProvider objects in the tenancy and cannot be changed.
+
+ product_type +
str
+
    Choices: +
  • IDCS
  • +
  • ADFS
  • +
+
+
The identity provider service or product. Supported identity providers are Oracle Identity Cloud Service (IDCS) and Microsoft Active Directory Federation Services (ADFS).
+
+ protocol +
str
+
    Choices: +
  • SAML2 ←
  • +
+
+
The protocol used for federation.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ state +
str
+
    Choices: +
  • present ←
  • +
  • absent
  • +
+
+
Create or update an identity provider with state=present. Use state=absent to delete an identity provider.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ wait +
bool
+
    Choices: +
  • no
  • +
  • yes ←
  • +
+
+
Whether to wait for create or delete operation to complete.
+
+ wait_timeout + + Default:
1200
+
+
Time, in seconds, to wait when wait=yes.
+
+ wait_until + + +
The lifecycle state to wait for the resource to transition into when wait=yes. By default, when wait=yes, we wait for the resource to get into ACTIVE/ATTACHED/AVAILABLE/PROVISIONED/ RUNNING applicable lifecycle state during create operation & to get into DELETED/DETACHED/ TERMINATED lifecycle state during delete operation.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Create an identity provider + oci_identity_provider: + compartment_id: 'ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx' + description: test identity provider + freeform_attributes: + clientId: app_sf3kdjf3 + metadata_url: https://myidpserver/FederationMetadata/2007-06/FederationMetadata.xml + name: mytestidentityprovider + product_type: ADFS + protocol: SAML2 + + - name: Update description of an identity provider + oci_identity_provider: + identity_provider_id: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx + description: updated description + + - name: Delete the specified identity provider + oci_identity_provider: + identity_provider_id: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx + state: absent + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + +
KeyReturnedDescription
+ identity_provider +
dict
+
On successful create and update operation +
Information about the identity provider
+
+
Sample:
+
{'lifecycle_state': 'AVAILABLE', 'dns_label': 'ansiblevcn', 'display_name': 'ansible_vcn', 'default_route_table_id': 'ocid1.routetable.oc1.phx.xxxxxEXAMPLExxxxx', 'default_dhcp_options_id': 'ocid1.dhcpoptions.oc1.phx.xxxxxEXAMPLExxxxx', 'time_created': '2017-11-13T20:22:40.626000+00:00', 'vcn_domain_name': 'ansiblevcn.oraclevcn.com', 'compartment_id"': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'cidr_block': '10.0.0.0/16', 'id': 'ocid1.vcn.oc1.phx.xxxxxEXAMPLExxxxx', 'default_security_list_id': 'ocid1.securitylist.oc1.phx.xxxxxEXAMPLExxxxx'}
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_idp_group_mapping_facts_module.rst b/docs/modules/oci_idp_group_mapping_facts_module.rst new file mode 100644 index 0000000..c1578c5 --- /dev/null +++ b/docs/modules/oci_idp_group_mapping_facts_module.rst @@ -0,0 +1,346 @@ +:source: cloud/oracle/oci_idp_group_mapping_facts.py + +:orphan: + +.. _oci_idp_group_mapping_facts_module: + + +oci_idp_group_mapping_facts - Retrieve details of all Identity Provider (IdP) group mappings for a given Identity Provider. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module retrieves details of all Identity Provider (IdP) group mappings for a given Identity Provier. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ identity_provider_id +
str

required
+ +
The identifier of the identity provider to fetch group mappings for.
+
+ mapping_id +
str
+ +
The identifier of the group mapping to fetch the details of.
+

aliases: id
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get details of all IdP group mappings for a given identity provider + oci_idp_group_mapping_facts: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + + - name: Get the details of a single IdP group mapping + oci_idp_group_mapping_facts: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + mapping_id: 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba' + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ idp_group_mappings +
complex
+
on success +
Information about one or more IdP group mappings
+
+
Sample:
+
[{'idp_id': 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq', 'inactive_status': None, 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq', 'lifecycle_state': 'ACTIVE', 'time_created': '2016-08-25T21:10:29.600Z', 'idp_group_name': 'IdPGroupName', 'group_id': 'ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda', 'id': 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba'}]
+
  + idp_id +
string
+
always +
The identifier of the Identity Provider this mapping belongs to.
+
+
Sample:
+
ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq
+
  + inactive_status +
int
+
always +
The detailed status of INACTIVE lifecycle_state.
+
+
  + compartment_id +
string
+
always +
The identifier of the tenancy containing the Identity Provider.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq
+
  + lifecycle_state +
string
+
always +
The mapping's current state. After creating a mapping object, make sure its lifecycle_state changes from CREATING to ACTIVE before using it.
+
+
Sample:
+
ACTIVE
+
  + time_created +
datetime
+
always +
Date and time the mapping was created.
+
+
Sample:
+
2016-08-25 21:10:29.600000
+
  + idp_group_name +
string
+
always +
The name of the IdP group that is mapped to the IAM Service group.
+
+
Sample:
+
IdPGroupName
+
  + group_id +
string
+
always +
The identifier of the IAM Service group that is mapped to the IdP group.
+
+
Sample:
+
ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda
+
  + id +
string
+
always +
The identifier of the IdpGroupMapping.
+
+
Sample:
+
ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Mike Ross (@mikeross) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_idp_group_mapping_module.rst b/docs/modules/oci_idp_group_mapping_module.rst new file mode 100644 index 0000000..789ac40 --- /dev/null +++ b/docs/modules/oci_idp_group_mapping_module.rst @@ -0,0 +1,390 @@ +:source: cloud/oracle/oci_idp_group_mapping.py + +:orphan: + +.. _oci_idp_group_mapping_module: + + +oci_idp_group_mapping - Create, update and delete Identity Provider (IdP) group mappings. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- Create, update and delete IdP group mappings. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ group_id +
str
+ +
The identifier of the IAM Service group that is mapped to the IdP group.
+
+ identity_provider_id +
str

required
+ +
The identifier of the identity provider the IdP group mapping belongs to.
+
+ idp_group_name +
str
+ +
The IdP group name.
+
+ mapping_id +
str
+ +
The identifier of the IdpGroupMapping to update or delete.
+

aliases: id
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ state + +
    Choices: +
  • present ←
  • +
  • absent
  • +
+
+
Create, update or delete an IdP group mapping. For state=present, if the mapping does not exist, it gets created. If it does exist, it gets updated. For state=absent, the mapping gets deleted.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Create IdP group mapping + oci_idp_group_mapping: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + group_id: 'ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda' + idp_group_name: IdPGroupName + + - name: Update IdP group name of an IdP group mapping + oci_idp_group_mapping: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + mapping_id: 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba' + idp_group_name: IdPGroupName + group_id: 'ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda' + + - name: Deletes an IdP group mapping + oci_idp_group_mapping: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + mapping_id: 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba' + state: "absent" + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ idp_group_mapping +
complex
+
on success +
Attributes of the created / updated IdP group mapping
+
+
Sample:
+
{'idp_id': 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq', 'inactive_status': None, 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq', 'lifecycle_state': 'ACTIVE', 'time_created': '2016-08-25T21:10:29.600Z', 'idp_group_name': 'IdPGroupName', 'group_id': 'ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda', 'id': 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba'}
+
  + idp_id +
string
+
always +
The identifier of the Identity Provider this mapping belongs to.
+
+
Sample:
+
ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq
+
  + inactive_status +
int
+
always +
The detailed status of INACTIVE lifecycle_state.
+
+
  + compartment_id +
string
+
always +
The identifier of the tenancy containing the Identity Provider.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq
+
  + lifecycle_state +
string
+
always +
The mapping's current state. After creating a mapping object, make sure its lifecycle_state changes from CREATING to ACTIVE before using it.
+
+
Sample:
+
ACTIVE
+
  + time_created +
datetime
+
always +
Date and time the mapping was created.
+
+
Sample:
+
2016-08-25 21:10:29.600000
+
  + idp_group_name +
string
+
always +
The name of the IdP group that is mapped to the IAM Service group.
+
+
Sample:
+
IdPGroupName
+
  + group_id +
string
+
always +
The identifier of the IAM Service group that is mapped to the IdP group.
+
+
Sample:
+
ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda
+
  + id +
string
+
always +
The identifier of the IdpGroupMapping.
+
+
Sample:
+
ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Mike Ross (@mikeross) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_instance_configuration_facts_module.rst b/docs/modules/oci_instance_configuration_facts_module.rst index f7c04b7..108c045 100644 --- a/docs/modules/oci_instance_configuration_facts_module.rst +++ b/docs/modules/oci_instance_configuration_facts_module.rst @@ -215,7 +215,7 @@ Common return values are documented :ref:`here `, the foll
List of instance configuration information

Sample:
-
[{'instance-details': {'block-volumes': None, 'secondary-vnics': None, 'instance-type': 'compute', 'launch-details': {'source-details': {'source-type': 'image', 'image-id': 'ocid1.image.oc1.iad.xxxxxEXAMPLExxxxx...ayda'}, 'extended-metadata': None, 'defined-tags': None, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'shape': 'VM.Standard1.1', 'ipxe-script': None, 'create-vnic-details': {'hostname-label': None, 'assign-public-ip': True, 'private-ip': None, 'display-name': 'siva-test-3', 'skip-source-dest-check': False, 'subnet-id': None}, 'availability-domain': None, 'display-name': 'siva-test-3', 'freeform-tags': None, 'metadata': {'user_data': 'dW5kZWZpbmVk', 'ssh_authorized_keys': 'ssh-rsa ...k8Id/ug/xxxxxEXAMPLExxxxx...RYzAEYT foo@bar'}}}, 'time-created': '2018-11-07T04:16:20.454000+00:00', 'defined-tags': {}, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'id': 'ocid1.instanceconfiguration.oc1.iad.xxxxxEXAMPLExxxxx...ejka', 'display-name': 'siva-test-conf-3', 'freeform-tags': {}, 'deferred-fields': ['instanceDetails.launchDetails.availabilityDomain', 'instanceDetails.launchDetails.createVnicDetails.subnetId']}]
+
[{'instance-details': {'block-volumes': None, 'secondary-vnics': None, 'instance-type': 'compute', 'launch-details': {'source-details': {'source-type': 'image', 'image-id': 'ocid1.image.oc1.iad.xxxxxEXAMPLExxxxx...ayda'}, 'extended-metadata': None, 'defined-tags': None, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'shape': 'VM.Standard2.1', 'ipxe-script': None, 'create-vnic-details': {'hostname-label': None, 'assign-public-ip': True, 'private-ip': None, 'display-name': 'siva-test-3', 'skip-source-dest-check': False, 'subnet-id': None}, 'availability-domain': None, 'display-name': 'siva-test-3', 'freeform-tags': None, 'metadata': {'user_data': 'dW5kZWZpbmVk', 'ssh_authorized_keys': 'ssh-rsa ...k8Id/ug/xxxxxEXAMPLExxxxx...RYzAEYT foo@bar'}}}, 'time-created': '2018-11-07T04:16:20.454000+00:00', 'defined-tags': {}, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'id': 'ocid1.instanceconfiguration.oc1.iad.xxxxxEXAMPLExxxxx...ejka', 'display-name': 'siva-test-conf-3', 'freeform-tags': {}, 'deferred-fields': ['instanceDetails.launchDetails.availabilityDomain', 'instanceDetails.launchDetails.createVnicDetails.subnetId']}]
diff --git a/docs/modules/oci_instance_configuration_module.rst b/docs/modules/oci_instance_configuration_module.rst index 4369772..f0ea05f 100644 --- a/docs/modules/oci_instance_configuration_module.rst +++ b/docs/modules/oci_instance_configuration_module.rst @@ -907,7 +907,7 @@ Examples .. code-block:: yaml+jinja - - name: Create an instance configuration that describes launch details for a compute instance of VM.Standard1.1 shape + - name: Create an instance configuration that describes launch details for a compute instance of VM.Standard2.1 shape and a specific image. No details are provided for additional block volume attachments or secondary VNICs oci_instance_configuration: name: "backend-servers" @@ -916,14 +916,14 @@ Examples instance_type: "compute" launch_details: compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...vm62xq" - shape: "VM.Standard1.1" + shape: "VM.Standard2.1" source_details: source_type: "image" image_id: "ocid1.image.oc1.phx.xxxxxEXAMPLExxxxx...sa7klnoa" metadata: foo: bar - - name: Create an instance configuration that describes launch details for a compute instance of VM.Standard1.1 shape + - name: Create an instance configuration that describes launch details for a compute instance of VM.Standard2.1 shape and a specific image, with additional block volume details (stating that a new block volume must be created and that it must be a clone of an existing volume, and an existing iscsi volume be attached) oci_instance_configuration: @@ -933,7 +933,7 @@ Examples instance_type: "compute" launch_details: compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...vm62xq" - shape: "VM.Standard1.1" + shape: "VM.Standard2.1" source_details: source_type: "image" image_id: "ocid1.image.oc1.phx.xxxxxEXAMPLExxxxx...sa7klnoa" @@ -981,7 +981,7 @@ Common return values are documented :ref:`here `, the foll
Information about the Instance Configuration

Sample:
-
{'instance-details': {'block-volumes': None, 'secondary-vnics': None, 'instance-type': 'compute', 'launch-details': {'source-details': {'source-type': 'image', 'image-id': 'ocid1.image.oc1.iad.xxxxxEXAMPLExxxxx...ayda'}, 'extended-metadata': None, 'defined-tags': None, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'shape': 'VM.Standard1.1', 'ipxe-script': None, 'create-vnic-details': {'hostname-label': None, 'assign-public-ip': True, 'private-ip': None, 'display-name': 'siva-test-3', 'skip-source-dest-check': False, 'subnet-id': None}, 'availability-domain': None, 'display-name': 'siva-test-3', 'freeform-tags': None, 'metadata': {'user_data': 'dW5kZWZpbmVk', 'ssh_authorized_keys': 'ssh-rsa ...k8Id/ug/xxxxxEXAMPLExxxxx...RYzAEYT foo@bar'}}}, 'time-created': '2018-11-07T04:16:20.454000+00:00', 'defined-tags': {}, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'id': 'ocid1.instanceconfiguration.oc1.iad.xxxxxEXAMPLExxxxx...ejka', 'display-name': 'siva-test-conf-3', 'freeform-tags': {}, 'deferred-fields': ['instanceDetails.launchDetails.availabilityDomain', 'instanceDetails.launchDetails.createVnicDetails.subnetId']}
+
{'instance-details': {'block-volumes': None, 'secondary-vnics': None, 'instance-type': 'compute', 'launch-details': {'source-details': {'source-type': 'image', 'image-id': 'ocid1.image.oc1.iad.xxxxxEXAMPLExxxxx...ayda'}, 'extended-metadata': None, 'defined-tags': None, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'shape': 'VM.Standard2.1', 'ipxe-script': None, 'create-vnic-details': {'hostname-label': None, 'assign-public-ip': True, 'private-ip': None, 'display-name': 'siva-test-3', 'skip-source-dest-check': False, 'subnet-id': None}, 'availability-domain': None, 'display-name': 'siva-test-3', 'freeform-tags': None, 'metadata': {'user_data': 'dW5kZWZpbmVk', 'ssh_authorized_keys': 'ssh-rsa ...k8Id/ug/xxxxxEXAMPLExxxxx...RYzAEYT foo@bar'}}}, 'time-created': '2018-11-07T04:16:20.454000+00:00', 'defined-tags': {}, 'compartment-id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...mkwq', 'id': 'ocid1.instanceconfiguration.oc1.iad.xxxxxEXAMPLExxxxx...ejka', 'display-name': 'siva-test-conf-3', 'freeform-tags': {}, 'deferred-fields': ['instanceDetails.launchDetails.availabilityDomain', 'instanceDetails.launchDetails.createVnicDetails.subnetId']}
diff --git a/docs/modules/oci_instance_facts_module.rst b/docs/modules/oci_instance_facts_module.rst index 7773cc7..6a343c8 100644 --- a/docs/modules/oci_instance_facts_module.rst +++ b/docs/modules/oci_instance_facts_module.rst @@ -97,7 +97,7 @@ Parameters availability_domain - +
str
@@ -107,7 +107,7 @@ Parameters compartment_id - +
str
@@ -147,7 +147,7 @@ Parameters instance_id - +
str
@@ -158,7 +158,7 @@ Parameters lifecycle_state - +
str
    Choices:
  • PROVISIONING
  • @@ -172,7 +172,7 @@ Parameters
-
A filter to only return resources that match the given lifecycle state. The state value is case-insensitive. Allowed values are "PROVISIONING", "RUNNING", "STARTING", "STOPPING", "STOPPED", "CREATING_IMAGE", "TERMINATING", "TERMINATED"
+
A filter to only return resources that match the given lifecycle state. The state value is case-insensitive.
diff --git a/docs/modules/oci_instance_module.rst b/docs/modules/oci_instance_module.rst index 06320d7..0bd5b36 100644 --- a/docs/modules/oci_instance_module.rst +++ b/docs/modules/oci_instance_module.rst @@ -178,7 +178,7 @@ Parameters -
Used with exact_count to determine how many compute instances matching the specific tag criteria count_tag must be running. Only defined_tags associated with an instance are considered for matching against count_tag.
+
Used with exact_count to determine how many compute instances matching the specific tag criteria count_tag must be running. Only defined_tags associated with an instance are considered for matching against count_tag. This option is deprecated and will be removed in a future release. Please use oci_instance_pool instead to create multiple compute instances.
@@ -213,7 +213,7 @@ Parameters -
Whether to scale up and down exact_count instances in parallel. By default, exact_count instances are launched or terminated in parallel.
+
Whether to scale up and down exact_count instances in parallel. By default, exact_count instances are launched or terminated in parallel. This option is deprecated and will be removed in a future release. Please use oci_instance_pool instead to create multiple compute instances.
@@ -223,7 +223,7 @@ Parameters -
Indicates how many instances that match the count_tag option should be running. This must be used with state=present and a valid count_tag. If the number of compute instances that match count_tag is lesser than exact_count, additional compute instances would be provisioned to match the desired exact_count. If the number of matching compute instances is larger than exact_count, compute instances would be terminated to match the desired exact_count. The latest launch instance(s) from the set of instances that match count_tag are picked for termination. Private IP assignments through private_ip, and specification of hostname_label and volume_details and boot_volume_details is not supported with exact_count and count_tag. By default, an auto-incremented integer value is suffixed to the value of display_name and assigned as the display_name of a newly provisioned instance. For example, if display_name is 'my_web_server', new compute instances would be called 'my_web_server_0', 'my_web_server_1' and so on. To control the generated display name in a fine-grained manner, use "printf" style format in display_name such as 'my_%d_web_server'.
+
Indicates how many instances that match the count_tag option should be running. This must be used with state=present and a valid count_tag. If the number of compute instances that match count_tag is lesser than exact_count, additional compute instances would be provisioned to match the desired exact_count. If the number of matching compute instances is larger than exact_count, compute instances would be terminated to match the desired exact_count. The latest launch instance(s) from the set of instances that match count_tag are picked for termination. Private IP assignments through private_ip, and specification of hostname_label and volume_details and boot_volume_details is not supported with exact_count and count_tag. By default, an auto-incremented integer value is suffixed to the value of display_name and assigned as the display_name of a newly provisioned instance. For example, if display_name is 'my_web_server', new compute instances would be called 'my_web_server_0', 'my_web_server_1' and so on. To control the generated display name in a fine-grained manner, use "printf" style format in display_name such as 'my_%d_web_server'. This option is deprecated and will be removed in a future release. Please use oci_instance_pool instead to create multiple compute instances.
@@ -318,7 +318,7 @@ Parameters -
When enable_parallel_requests=True, indicates the number of maximum parallel operations that are used to launch or terminate exact_count instances. The default number of threads used is the number of cores in your machine.
+
When enable_parallel_requests=True, indicates the number of maximum parallel operations that are used to launch or terminate exact_count instances. The default number of threads used is the number of cores in your machine. This option is deprecated and will be removed in a future release. Please use oci_instance_pool instead to create multiple compute instances.
diff --git a/docs/modules/oci_node_pool_facts_module.rst b/docs/modules/oci_node_pool_facts_module.rst index c6419f8..0e40e6f 100644 --- a/docs/modules/oci_node_pool_facts_module.rst +++ b/docs/modules/oci_node_pool_facts_module.rst @@ -230,7 +230,7 @@ Common return values are documented :ref:`here `, the foll
List of node pool details

Sample:
-
[{'node_shape': 'VM.Standard1.1', 'name': 'test_node_pool', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'initial_node_labels': [{'key': 'type', 'value': 'standard'}, {'key': 'stage', 'value': 'prod'}], 'node_image_id': 'ocid1.image.oc1..xxxxxEXAMPLExxxxx', 'id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'cluster_id': 'ocid1.cluster.oc1..xxxxxEXAMPLExxxxx', 'quantity_per_subnet': 1, 'node_image_name': 'Oracle-Linux-7.4', 'ssh_public_key': '', 'subnet_ids': ['ocid1.subnet..xxxxxEXAMPLExxxxx'], 'kubernetes_version': 'v1.9.7', 'nodes': [{'lifecycle_state': 'UPDATING', 'availability_domain': 'IwGV:US-ASHBURN-AD-1', 'name': 'oke-c3dsodfgezw-n3wiztggrrt-st2au5vefpq-0', 'subnet_id': 'ocid1.subnet.oc1..xxxxxEXAMPLExxxxx', 'public_ip': '129.213.129.26', 'node_pool_id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'node_error': None, 'lifecycle_details': 'waiting for running compute instance', 'id': 'ocid1.instance.oc1..xxxxxEXAMPLExxxxx'}]}]
+
[{'node_shape': 'VM.Standard2.1', 'name': 'test_node_pool', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'initial_node_labels': [{'key': 'type', 'value': 'standard'}, {'key': 'stage', 'value': 'prod'}], 'node_image_id': 'ocid1.image.oc1..xxxxxEXAMPLExxxxx', 'id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'cluster_id': 'ocid1.cluster.oc1..xxxxxEXAMPLExxxxx', 'quantity_per_subnet': 1, 'node_image_name': 'Oracle-Linux-7.4', 'ssh_public_key': '', 'subnet_ids': ['ocid1.subnet..xxxxxEXAMPLExxxxx'], 'kubernetes_version': 'v1.9.7', 'nodes': [{'lifecycle_state': 'UPDATING', 'availability_domain': 'IwGV:US-ASHBURN-AD-1', 'name': 'oke-c3dsodfgezw-n3wiztggrrt-st2au5vefpq-0', 'subnet_id': 'ocid1.subnet.oc1..xxxxxEXAMPLExxxxx', 'public_ip': '129.213.129.26', 'node_pool_id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'node_error': None, 'lifecycle_details': 'waiting for running compute instance', 'id': 'ocid1.instance.oc1..xxxxxEXAMPLExxxxx'}]}]
@@ -244,7 +244,7 @@ Common return values are documented :ref:`here `, the foll
The name of the node shape of the nodes in the node pool.

Sample:
-
VM.Standard1.1
+
VM.Standard2.1
diff --git a/docs/modules/oci_node_pool_module.rst b/docs/modules/oci_node_pool_module.rst index 538c327..c236d33 100644 --- a/docs/modules/oci_node_pool_module.rst +++ b/docs/modules/oci_node_pool_module.rst @@ -377,7 +377,7 @@ Examples name: test_node_pool kubernetes_version: "v1.9.7" node_image_name: "Oracle-Linux-7.4" - node_shape: "VM.Standard1.1" + node_shape: "VM.Standard2.1" quantity_per_subnet: 1 subnet_ids: - "ocid1.subnet.oc1..xxxxxEXAMPLExxxxx...abcd" @@ -431,7 +431,7 @@ Common return values are documented :ref:`here `, the foll
Information about the node pool

Sample:
-
{'node_shape': 'VM.Standard1.1', 'name': 'test_node_pool', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'initial_node_labels': [{'key': 'vm_type', 'value': 'standard'}, {'key': 'stage', 'value': 'prod'}], 'node_image_id': 'ocid1.image.oc1..xxxxxEXAMPLExxxxx', 'id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'cluster_id': 'ocid1.cluster.oc1..xxxxxEXAMPLExxxxx', 'quantity_per_subnet': 1, 'node_image_name': 'Oracle-Linux-7.4', 'ssh_public_key': '', 'subnet_ids': ['ocid1.subnet..xxxxxEXAMPLExxxxx'], 'kubernetes_version': 'v1.9.7', 'nodes': [{'lifecycle_state': 'UPDATING', 'availability_domain': 'IwGV:US-ASHBURN-AD-1', 'name': 'oke-c3dsodfgezw-n3wiztggrrt-st2au5vefpq-0', 'subnet_id': 'ocid1.subnet.oc1..xxxxxEXAMPLExxxxx', 'public_ip': '129.213.129.26', 'node_pool_id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'node_error': None, 'lifecycle_details': 'waiting for running compute instance', 'id': 'ocid1.instance.oc1..xxxxxEXAMPLExxxxx'}]}
+
{'node_shape': 'VM.Standard2.1', 'name': 'test_node_pool', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'initial_node_labels': [{'key': 'vm_type', 'value': 'standard'}, {'key': 'stage', 'value': 'prod'}], 'node_image_id': 'ocid1.image.oc1..xxxxxEXAMPLExxxxx', 'id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'cluster_id': 'ocid1.cluster.oc1..xxxxxEXAMPLExxxxx', 'quantity_per_subnet': 1, 'node_image_name': 'Oracle-Linux-7.4', 'ssh_public_key': '', 'subnet_ids': ['ocid1.subnet..xxxxxEXAMPLExxxxx'], 'kubernetes_version': 'v1.9.7', 'nodes': [{'lifecycle_state': 'UPDATING', 'availability_domain': 'IwGV:US-ASHBURN-AD-1', 'name': 'oke-c3dsodfgezw-n3wiztggrrt-st2au5vefpq-0', 'subnet_id': 'ocid1.subnet.oc1..xxxxxEXAMPLExxxxx', 'public_ip': '129.213.129.26', 'node_pool_id': 'ocid1.nodepool.oc1..xxxxxEXAMPLExxxxx', 'node_error': None, 'lifecycle_details': 'waiting for running compute instance', 'id': 'ocid1.instance.oc1..xxxxxEXAMPLExxxxx'}]}
@@ -445,7 +445,7 @@ Common return values are documented :ref:`here `, the foll
The name of the node shape of the nodes in the node pool.

Sample:
-
VM.Standard1.1
+
VM.Standard2.1
diff --git a/docs/modules/oci_node_pool_options_facts_module.rst b/docs/modules/oci_node_pool_options_facts_module.rst index 53aa992..2ec3d2f 100644 --- a/docs/modules/oci_node_pool_options_facts_module.rst +++ b/docs/modules/oci_node_pool_options_facts_module.rst @@ -195,7 +195,7 @@ Common return values are documented :ref:`here `, the foll
Options available for node pools

Sample:
-
{'images': ['Oracle-Linux-7.4', 'Oracle-Linux-7.5'], 'shapes': ['VM.Standard2.1', 'VM.Standard2.2', 'VM.Standard1.1', 'VM.Standard1.2', 'VM.DenseIO1.4'], 'kubernetes_versions': ['v1.8.11', 'v1.9.7', 'v1.10.3', 'v1.11.1']}
+
{'images': ['Oracle-Linux-7.4', 'Oracle-Linux-7.5'], 'shapes': ['VM.Standard2.1', 'VM.Standard2.2', 'VM.Standard2.4', 'VM.Standard2.8', 'VM.DenseIO2.8'], 'kubernetes_versions': ['v1.8.11', 'v1.9.7', 'v1.10.3', 'v1.11.1']}
diff --git a/docs/modules/oci_security_list_module.rst b/docs/modules/oci_security_list_module.rst index f3302f4..cc186fc 100644 --- a/docs/modules/oci_security_list_module.rst +++ b/docs/modules/oci_security_list_module.rst @@ -39,12 +39,12 @@ Parameters - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - +
str
+
str
+
str
+
str
+
str
ParameterParameter Choices/Defaults Comments
+ api_user @@ -54,7 +54,7 @@ Parameters
+ api_user_fingerprint @@ -64,7 +64,7 @@ Parameters
+ api_user_key_file @@ -74,7 +74,7 @@ Parameters
+ api_user_key_pass_phrase @@ -84,7 +84,7 @@ Parameters
+ auth_type @@ -98,7 +98,7 @@ Parameters
+ compartment_id @@ -108,7 +108,7 @@ Parameters
+ config_file_location @@ -118,7 +118,7 @@ Parameters
+ config_profile_name @@ -128,7 +128,7 @@ Parameters
+ defined_tags @@ -138,7 +138,7 @@ Parameters
+ delete_security_rules
bool
@@ -152,7 +152,7 @@ Parameters
+ display_name @@ -163,7 +163,7 @@ Parameters
+ egress_security_rules @@ -174,7 +174,7 @@ Parameters
+ icmp_options @@ -185,7 +185,7 @@ Parameters
+ udp_options @@ -196,7 +196,7 @@ Parameters
+ destination_type @@ -211,7 +211,7 @@ Parameters
+ tcp_options @@ -219,10 +219,35 @@ Parameters
Valid only for TCP. Use to specify particular destination ports for TCP rules. If TCP specified as the protocol but omit this object, then all destination ports are allowed.
+ source_port_range + + +
The source port range for the egress rule. Intger values for min port number and max port number should be provided.
+
+ destination_port_range + + +
The destination port range for the egress rule. Intger values for min port number and max port number should be provided.
+
destination
required
@@ -233,7 +258,7 @@ Parameters
+ is_stateless @@ -248,7 +273,7 @@ Parameters
+ protocol
required
@@ -264,7 +289,7 @@ Parameters
+ force_create
bool
@@ -278,7 +303,7 @@ Parameters
+ freeform_tags @@ -288,7 +313,7 @@ Parameters
+ ingress_security_rules @@ -299,7 +324,7 @@ Parameters
+ source_type @@ -314,7 +339,7 @@ Parameters
+ icmp_options @@ -325,7 +350,7 @@ Parameters
+ udp_options @@ -336,7 +361,7 @@ Parameters
+ source
required
@@ -347,7 +372,7 @@ Parameters
+ tcp_options @@ -355,10 +380,35 @@ Parameters
Valid only for TCP. Use to specify particular destination ports for TCP rules. If TCP specified as the protocol but omit this object, then all destination ports are allowed.
+ source_port_range + + +
The source port range for the ingress rule. Intger values for min port number and max port number should be provided.
+
+ destination_port_range + + +
The destination port range for the ingress rule. Intger values for min port number and max port number should be provided.
+
is_stateless @@ -373,7 +423,7 @@ Parameters
+ protocol
required
@@ -389,7 +439,7 @@ Parameters
+ key_by @@ -399,7 +449,7 @@ Parameters
+ purge_security_rules
bool
@@ -413,7 +463,7 @@ Parameters
+ region @@ -423,7 +473,7 @@ Parameters
+ security_list_id @@ -434,7 +484,7 @@ Parameters
+ state @@ -448,7 +498,7 @@ Parameters
+ tenancy @@ -458,7 +508,7 @@ Parameters
+ vcn_id @@ -468,7 +518,7 @@ Parameters
+ wait
bool
@@ -482,7 +532,7 @@ Parameters
+ wait_timeout @@ -493,7 +543,7 @@ Parameters
+ wait_until @@ -538,8 +588,8 @@ Examples protocol: '6' tcp_options: destination_port_range: - min: '22' - max: '22' + min: 22 + max: 22 - source: 'oci-iad-objectstorage' source_type: 'SERVICE_CIDR_BLOCK' is_stateless: False @@ -563,8 +613,8 @@ Examples protocol: '6' tcp_options: destination_port_range: - min: '25' - max: '30' + min: 25 + max: 30 purge_security_rules: 'yes' state: 'present' @@ -577,8 +627,8 @@ Examples protocol: '6' tcp_options: destination_port_range: - min: '25' - max: '30' + min: 25 + max: 30 delete_security_rules: 'yes' state: 'present' diff --git a/docs/modules/oci_vcn_module.rst b/docs/modules/oci_vcn_module.rst index 1f3fc04..91d9d4e 100644 --- a/docs/modules/oci_vcn_module.rst +++ b/docs/modules/oci_vcn_module.rst @@ -107,7 +107,7 @@ Parameters
compartment_id - @@ -147,7 +147,7 @@ Parameters
display_name - @@ -158,7 +158,7 @@ Parameters
dns_label - @@ -212,7 +212,7 @@ Parameters
state -
    Choices:
  • present ←
  • @@ -236,7 +236,7 @@ Parameters
vcn_id - diff --git a/docs/modules/oci_waas_certificate_facts_module.rst b/docs/modules/oci_waas_certificate_facts_module.rst new file mode 100644 index 0000000..33d7ca0 --- /dev/null +++ b/docs/modules/oci_waas_certificate_facts_module.rst @@ -0,0 +1,584 @@ +:source: cloud/oracle/oci_waas_certificate_facts.py + +:orphan: + +.. _oci_waas_certificate_facts_module: + + +oci_waas_certificate_facts - Retrieve details about WAAS certificates. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module retrieves information of a specific WAAS certificate or lists all the WAAS certificates in the given compartment. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ certificate_id +
str
+ +
The OCID of the SSL certificate used in the WAAS policy. Required to get information of a specific certificate.
+
+ compartment_id +
str
+ +
The OCID of the compartment.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ display_name +
list
+ +
Filter certificates using a list of display names.
+
+ id +
list
+ +
Filter certificates using a list of certificates OCIDs.
+
+ lifecycle_state +
list
+
    Choices: +
  • CREATING
  • +
  • ACTIVE
  • +
  • FAILED
  • +
  • UPDATING
  • +
  • DELETING
  • +
  • DELETED
  • +
+
+
Filter certificates using a list of lifecycle states.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ sort_by +
str
+
    Choices: +
  • id
  • +
  • compartmentId
  • +
  • displayName
  • +
  • notValidAfter
  • +
  • timeCreated
  • +
+
+
The value by which certificate summaries are sorted in a paginated 'List' call. If unspecified, defaults to timeCreated.
+
+ sort_order +
str
+
    Choices: +
  • ASC
  • +
  • DESC
  • +
+
+
The order in which to sort the results.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ time_created_greater_than_or_equal_to +
str
+ +
A filter that matches certificates created on or after the specified date-time.
+
+ time_created_less_than +
str
+ +
A filter that matches certificates created before the specified date-time.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get all the waas certificates in a compartment + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + + - name: Get a specific waas certificate using its OCID + oci_waas_certificate_facts: + certificate_id: ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx + + - name: Get waas certificate having the specified display name + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: examplewaascertificate + + - name: Get waas certificates in a compartment with given display names + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaascertificate1 + - examplewaascertificate2 + + - name: Filter waas certificates in a compartment using display_name, lifecycle_state and sort the results + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaascertificate1 + - examplewaascertificate2 + lifecycle_state: + - ACTIVE + sort_by: timeCreated + sort_order: DESC + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_certificates +
complex
+
on success +
List of waas certificates
+
+
Sample:
+
[{'time_not_valid_before': '2019-04-10T08:09:17+00:00', 'subject_name': {'state_province': 'KA', 'organization': 'Ansible', 'organizational_unit': None, 'locality': 'Bangalore', 'common_name': 'testcommonname', 'country': 'IN', 'email_address': None}, 'time_not_valid_after': '2024-04-08T08:09:17+00:00', 'time_created': '2019-04-10T10:05:35.634000+00:00', 'issuer_name': {'state_province': 'KA', 'organization': 'Ansible', 'organizational_unit': None, 'locality': 'Bangalore', 'common_name': 'testcommonname', 'country': 'IN', 'email_address': None}, 'signature_algorithm': None, 'id': 'ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx', 'lifecycle_state': 'ACTIVE', 'display_name': 'test waas certificate', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'defined_tags': None, 'issued_by': 'Ansible', 'freeform_tags': None, 'version': None, 'extensions': None, 'public_key_info': {'key_size': 2048, 'exponent': 65537, 'algorithm': 'RSA'}, 'serial_number': '9917593779878295042'}]
+
  + time_not_valid_before +
str
+
success +
The time_not_valid_before of this Certificate.
+
+
Sample:
+
2019-04-02 15:29:38
+
  + subject_name +
complex
+
success +
The subject_name of this Certificate.
+
+
Sample:
+
{'state_province': 'teststate', 'organization': 'testorg', 'organizational_unit': 'testorgunit', 'locality': 'testlocality', 'common_name': 'testcommonname', 'country': 'AU', 'email_address': 'test.email@address.com'}
+
  + time_not_valid_after +
str
+
success +
The date and time the certificate will expire, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2020-04-01 15:29:38
+
  + time_created +
str
+
success +
The date and time the certificate was created, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2019-04-02 17:12:42.454000
+
  + issuer_name +
complex
+
success +
The issuer_name of this Certificate.
+
+
Sample:
+
{'state_province': 'teststate', 'organization': 'testorg', 'organizational_unit': 'testorgunit', 'locality': 'testlocality', 'common_name': 'testcommonname', 'country': 'AU', 'email_address': 'test.email@address.com'}
+
  + signature_algorithm +
str
+
success +
The signature_algorithm of this Certificate.
+
+
Sample:
+
SHA-1
+
  + id +
str
+
success +
The OCID of the certificate.
+
+
Sample:
+
ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx
+
  + lifecycle_state +
str
+
success +
The current lifecycle state of the SSL certificate.
+
+
Sample:
+
ACTIVE
+
  + display_name +
str
+
success +
The user-friendly name of the certificate.
+
+
Sample:
+
testcertificate
+
  + compartment_id +
str
+
success +
The OCID of the certificate's compartment.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+
  + defined_tags +
str
+
success +
A key-value pair with a defined schema that restricts the values of tags. These predefined keys are scoped to namespaces.
+
+
Sample:
+
{'example_namespace': {'example_key': 'example_value'}}
+
  + issued_by +
str
+
success +
The issued_by of this Certificate.
+
+
Sample:
+
testissuer
+
  + freeform_tags +
complex
+
success +
A simple key-value pair without any defined schema.
+
+
Sample:
+
{'example_freeform_key': 'example_freeform_value'}
+
  + version +
int
+
success +
The version of this Certificate.
+
+
Sample:
+
2
+
  + extensions +
list
+
success +
The extensions of this Certificate.
+
+
Sample:
+
[{'is_critical': None, 'name': 'subjectKeyIdentifier', 'value': 'A6:B2:56:1X:1X:1X:1X:8C:F6'}]
+
  + public_key_info +
complex
+
success +
The public_key_info of this Certificate.
+
+
Sample:
+
{'key_size': 2048, 'exponent': 65537, 'algorithm': 'RSA'}
+
  + serial_number +
str
+
success +
The serial_number of this Certificate.
+
+
Sample:
+
100000000000710
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_certificate_module.rst b/docs/modules/oci_waas_certificate_module.rst new file mode 100644 index 0000000..9180498 --- /dev/null +++ b/docs/modules/oci_waas_certificate_module.rst @@ -0,0 +1,619 @@ +:source: cloud/oracle/oci_waas_certificate.py + +:orphan: + +.. _oci_waas_certificate_module: + + +oci_waas_certificate - Manage WAAS certificates in OCI +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module allows the user to create, delete and update WAAS certificates in OCI. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ certificate_data +
str
+ +
The data of the SSL certificate.
+
+ certificate_id +
str
+ +
The OCID of the SSL certificate used in the WAAS policy. Required when deleting a WAAS certificate with state=absent or updating a WAAS certificate with state=present. This option is mutually exclusive with compartment_id.
+
+ compartment_id +
str
+ +
The OCID of the compartment in which to create the SSL certificate.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ defined_tags + + +
Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/resourcetags.htm.
+
+ display_name +
str
+ +
A user-friendly name for the SSL certificate. The name can be changed and does not need to be unique.
+
+ force_create +
bool
+
    Choices: +
  • no ←
  • +
  • yes
  • +
+
+
Whether to attempt non-idempotent creation of a resource. By default, create resource is an idempotent operation, and doesn't create the resource if it already exists. Setting this option to true, forcefully creates a copy of the resource, even if it already exists.This option is mutually exclusive with key_by.
+
+ freeform_tags + + +
Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/resourcetags.htm.
+
+ is_trust_verification_disabled +
bool
+
    Choices: +
  • no
  • +
  • yes
  • +
+
+
The is_trust_verification_disabled of this certificate. Set to true if the SSL certificate is self-signed.
+
+ key_by + + +
The list of comma-separated attributes of this resource which should be used to uniquely identify an instance of the resource. By default, all the attributes of a resource except freeform_tags are used to uniquely identify a resource.
+
+ private_key_data +
str
+ +
The private key data of the SSL certificate.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ state + +
    Choices: +
  • present ←
  • +
  • absent
  • +
+
+
Create or update a WAAS certificate with state=present. Use state=absent to delete a WAAS certificate.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ wait +
bool
+
    Choices: +
  • no
  • +
  • yes ←
  • +
+
+
Whether to wait for create or delete operation to complete.
+
+ wait_timeout + + Default:
1200
+
+
Time, in seconds, to wait when wait=yes.
+
+ wait_until + + +
The lifecycle state to wait for the resource to transition into when wait=yes. By default, when wait=yes, we wait for the resource to get into ACTIVE/ATTACHED/AVAILABLE/PROVISIONED/ RUNNING applicable lifecycle state during create operation & to get into DELETED/DETACHED/ TERMINATED lifecycle state during delete operation.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Create a waas certificate + oci_waas_certificate: + compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx" + display_name: "test_waas_certificate" + certificate_data: "{{ lookup('file', '/path/to/cert/file') }}" + private_key_data: "{{ lookup('file', '/path/to/private/key') }}" + is_trust_verification_disabled: True + + - name: Update display name of the waas certificate + oci_waas_certificate: + certificate_id: "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx" + display_name: "updated_test_waas_certificate" + + - name: Delete a waas certificate + oci_waas_certificate: + certificate_id: "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx" + state: absent + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_certificate +
complex
+
on successful create and update operation +
Information about the WAAS certificate.
+
+
Sample:
+
{'time_not_valid_before': '2019-04-02T15:29:38+00:00', 'subject_name': {'state_province': 'teststate', 'organization': 'testorg', 'organizational_unit': 'testorgunit', 'locality': 'testlocality', 'common_name': 'testcommonname', 'country': 'AU', 'email_address': 'test.email@address.com'}, 'time_not_valid_after': '2020-04-01T15:29:38+00:00', 'time_created': '2019-04-13T21:51:09.088000+00:00', 'issuer_name': {'state_province': 'teststate', 'organization': 'testorg', 'organizational_unit': 'testorgunit', 'locality': 'testlocality', 'common_name': 'testcommonname', 'country': 'AU', 'email_address': 'test.email@address.com'}, 'signature_algorithm': None, 'id': 'ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx', 'lifecycle_state': 'ACTIVE', 'display_name': 'testcertificate', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'defined_tags': {'example_namespace': {'example_key': 'example_value'}}, 'issued_by': 'testissuer', 'freeform_tags': {'example_freeform_key': 'example_freeform_value'}, 'version': 2, 'extensions': [{'is_critical': None, 'name': 'subjectKeyIdentifier', 'value': 'A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6'}, {'is_critical': None, 'name': 'authorityKeyIdentifier', 'value': 'keyid:A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6'}, {'is_critical': True, 'name': 'basicConstraints', 'value': 'CA:TRUE'}], 'public_key_info': {'key_size': 2048, 'exponent': 65537, 'algorithm': 'RSA'}, 'serial_number': '100000000000710'}
+
  + time_not_valid_before +
str
+
success +
The time_not_valid_before of this Certificate.
+
+
Sample:
+
2019-04-02 15:29:38
+
  + subject_name +
complex
+
success +
The subject_name of this Certificate.
+
+
Sample:
+
{'state_province': 'teststate', 'organization': 'testorg', 'organizational_unit': 'testorgunit', 'locality': 'testlocality', 'common_name': 'testcommonname', 'country': 'AU', 'email_address': 'test.email@address.com'}
+
  + time_not_valid_after +
str
+
success +
The date and time the certificate will expire, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2020-04-01 15:29:38
+
  + time_created +
str
+
success +
The date and time the certificate was created, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2019-04-02 17:12:42.454000
+
  + issuer_name +
complex
+
success +
The issuer_name of this Certificate.
+
+
Sample:
+
{'state_province': 'teststate', 'organization': 'testorg', 'organizational_unit': 'testorgunit', 'locality': 'testlocality', 'common_name': 'testcommonname', 'country': 'AU', 'email_address': 'test.email@address.com'}
+
  + signature_algorithm +
str
+
success +
The signature_algorithm of this Certificate.
+
+
Sample:
+
SHA-1
+
  + id +
str
+
success +
The OCID of the certificate.
+
+
Sample:
+
ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx
+
  + lifecycle_state +
str
+
success +
The current lifecycle state of the SSL certificate.
+
+
Sample:
+
ACTIVE
+
  + display_name +
str
+
success +
The user-friendly name of the certificate.
+
+
Sample:
+
testcertificate
+
  + compartment_id +
str
+
success +
The OCID of the certificate's compartment.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+
  + defined_tags +
str
+
success +
A key-value pair with a defined schema that restricts the values of tags. These predefined keys are scoped to namespaces.
+
+
Sample:
+
{'example_namespace': {'example_key': 'example_value'}}
+
  + issued_by +
str
+
success +
The issued_by of this Certificate.
+
+
Sample:
+
testissuer
+
  + freeform_tags +
complex
+
success +
A simple key-value pair without any defined schema.
+
+
Sample:
+
{'example_freeform_key': 'example_freeform_value'}
+
  + version +
int
+
success +
The version of this Certificate.
+
+
Sample:
+
2
+
  + extensions +
list
+
success +
The extensions of this Certificate.
+
+
Sample:
+
[{'is_critical': None, 'name': 'subjectKeyIdentifier', 'value': 'A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6'}, {'is_critical': None, 'name': 'authorityKeyIdentifier', 'value': 'keyid:A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6'}, {'is_critical': True, 'name': 'basicConstraints', 'value': 'CA:TRUE'}]
+
  + public_key_info +
complex
+
success +
The public_key_info of this Certificate.
+
+
Sample:
+
{'key_size': 2048, 'exponent': 65537, 'algorithm': 'RSA'}
+
  + serial_number +
str
+
success +
The serial_number of this Certificate.
+
+
Sample:
+
100000000000710
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_edge_subnet_facts_module.rst b/docs/modules/oci_waas_edge_subnet_facts_module.rst new file mode 100644 index 0000000..34677a4 --- /dev/null +++ b/docs/modules/oci_waas_edge_subnet_facts_module.rst @@ -0,0 +1,285 @@ +:source: cloud/oracle/oci_waas_edge_subnet_facts.py + +:orphan: + +.. _oci_waas_edge_subnet_facts_module: + + +oci_waas_edge_subnet_facts - Retrieve facts of subnets corresponding the Web Application Firewall. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- Returns a list of subnets corresponding the Web Application Firewall. Return the list of the tenant's edge node subnets. Use these CIDR blocks to restrict incoming traffic to your origin. These subnets are owned by OCI and forward traffic to customer origins. They are not associated with specific regions or compartments. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ sort_by + +
    Choices: +
  • cidr
  • +
  • region
  • +
  • timeModified
  • +
+
+
The value by which edge node subnets are sorted.
+
+ sort_order +
str
+
    Choices: +
  • ASC
  • +
  • DESC
  • +
+
+
The order in which to sort the results.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get all the edge subnets + oci_waas_edge_subnet_facts: + + - name: Get all the edge subnets sorted by region + oci_waas_edge_subnet_facts: + sort_by: region + sort_order: DESC + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_edge_subnets +
complex
+
on success +
List of the tenant's edge node subnets.
+
+
Sample:
+
[{'cidr': '52.28.32.104', 'region': 'Europe', 'time_modified': '2017-01-30T13:27:08+00:00'}]
+
  + cidr +
str
+
success +
CIDR of an edge node subnet. This can include /24 or /8 addresses.
+
+
Sample:
+
52.28.32.104
+
  + region +
str
+
success +
The name of the region containing the indicated subnet.
+
+
Sample:
+
Europe
+
  + time_modified +
str
+
success +
The date and time the last change was made to the indicated edge node subnet, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2017-01-30 13:27:08
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_policy_facts_module.rst b/docs/modules/oci_waas_policy_facts_module.rst new file mode 100644 index 0000000..bd7efde --- /dev/null +++ b/docs/modules/oci_waas_policy_facts_module.rst @@ -0,0 +1,517 @@ +:source: cloud/oracle/oci_waas_policy_facts.py + +:orphan: + +.. _oci_waas_policy_facts_module: + + +oci_waas_policy_facts - Retrieve details about WAAS Policies. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module retrieves information of a specific WAAS policy or lists all WAAS policies in the given compartment. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ compartment_id +
str
+ +
The OCID of the compartment.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ display_name +
list
+ +
Filter policies using a list of display names.
+
+ id +
list
+ +
Filter policies using a list of policy OCIDs.
+
+ lifecycle_state +
list
+ +
Filter policies using a list of lifecycle states.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ sort_by +
str
+
    Choices: +
  • id
  • +
  • displayName
  • +
  • timeCreated
  • +
+
+
The value by which policies are sorted in a paginated 'List' call. If unspecified, defaults to timeCreated.
+
+ sort_order +
str
+
    Choices: +
  • ASC
  • +
  • DESC
  • +
+
+
The order in which to sort the results.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ time_created_greater_than_or_equal_to +
str
+ +
A filter that matches policies created on or after the specified date and time.
+
+ time_created_less_than +
str
+ +
A filter that matches policies created before the specified date-time.
+
+ waas_policy_id +
str
+ +
The OCID of the WAAS policy. Required to get information of a specific waas policy.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get all the waas policies in a compartment + oci_waas_policy_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + + - name: Get a specific waas policy using its OCID + oci_waas_policy_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + + - name: Get waas policy having the specified display name + oci_waas_policy_facts: + display_name: examplewaaspolicy + + - name: Get waas policies in a compartment with given display names + oci_waas_policy_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaaspolicy1 + - examplewaaspolicy2 + + - name: Filter waas policies in a compartment using display_name, lifecycle_state and sort the results + oci_waas_policy_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaaspolicy1 + - examplewaaspolicy2 + lifecycle_state: + - AVAILABLE + sort_by: timeCreated + sort_order: DESC + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_policies +
complex
+
on success +
List of waas policies
+
+
Sample:
+
[{'lifecycle_state': 'ACTIVE', 'domain': 'www.example.com', 'display_name': 'ansible_test_waas_policy', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'origins': {'LBaaS': {'http_port': 80, 'custom_headers': [], 'https_port': 443, 'uri': '1.2.3.4'}}, 'waf_config': {'origin': 'LBaaS', 'protection_rules': [{'action': 'OFF', 'description': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from IE', 'key': '941340', 'mod_security_rule_ids': ['941340'], 'labels': ['OWASP', 'OWASP-2017', 'CRS3', 'WASCTC', 'PCI', 'HTTP', 'A2', 'A2-2017', 'XSS', 'Cross-Site Scripting'], 'exclusions': [], 'name': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer'}], 'address_rate_limiting': {'allowed_rate_per_address': 1, 'is_enabled': False, 'block_response_code': 503, 'max_delayed_count_per_address': 10}, 'js_challenge': {'is_enabled': False, 'set_http_header': {'name': 'x-jsc-alerts', 'value': '{failed_amount}'}, 'failure_threshold': 10, 'action': 'DETECT', 'action_expiration_in_seconds': 60, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'JSC-403', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'device_fingerprint_challenge': {'is_enabled': False, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'max_address_count_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'max_address_count': 20, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'DFC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'whitelists': [], 'human_interaction_challenge': {'is_enabled': False, 'set_http_header': None, 'recording_period_in_seconds': 15, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'interaction_threshold': 3, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'HIC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'good_bots': [{'is_enabled': False, 'description': 'Googlebot is the search bot software used by Google.', 'key': '4a4c6e7b-4d89-4141-8555-ec3b22b90a73', 'name': 'Googlebot '}], 'access_rules': [], 'captchas': []}, 'defined_tags': {'example_namespace': {'example_key': 'example_value'}}, 'freeform_tags': {'example_freeform_key': 'example_freeform_value'}, 'time_created': '2019-03-22T13:02:55.563000+00:00', 'policy_config': {'certificate_id': None, 'is_https_enabled': False, 'is_https_forced': False}, 'cname': 'www-exampledomain-com.b.waas.oci.oraclecloud.net', 'additional_domains': ['www.exampledomain1.com', 'www.exampledomain2.com'], 'id': 'ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx'}]
+
  + lifecycle_state +
str
+
success +
The current lifecycle state of the WAAS policy.
+
+
Sample:
+
ACTIVE
+
  + domain +
str
+
success +
The web application domain that the WAAS policy protects.
+
+
Sample:
+
www.exampledomain.com
+
  + display_name +
str
+
success +
The user-friendly name of the WAAS policy.
+
+
Sample:
+
examplewaaspolicy1
+
  + compartment_id +
str
+
success +
The OCID of the WAAS policy's compartment.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+
  + origins +
complex
+
success +
A map of host to origin for the web application.
+
+
Sample:
+
{'LBaaS': {'http_port': 80, 'custom_headers': [], 'https_port': 443, 'uri': '1.2.3.4'}}
+
  + waf_config +
complex
+
success +
The WAF config of this policy.
+
+
Sample:
+
{'origin': 'LBaaS', 'protection_rules': [{'action': 'OFF', 'description': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from IE', 'key': '941340', 'mod_security_rule_ids': ['941340'], 'labels': ['OWASP', 'OWASP-2017', 'CRS3', 'WASCTC', 'PCI', 'HTTP', 'A2', 'A2-2017', 'XSS', 'Cross-Site Scripting'], 'exclusions': [], 'name': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer'}], 'address_rate_limiting': {'allowed_rate_per_address': 1, 'is_enabled': False, 'block_response_code': 503, 'max_delayed_count_per_address': 10}, 'js_challenge': {'is_enabled': False, 'set_http_header': {'name': 'x-jsc-alerts', 'value': '{failed_amount}'}, 'failure_threshold': 10, 'action': 'DETECT', 'action_expiration_in_seconds': 60, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'JSC-403', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'device_fingerprint_challenge': {'is_enabled': False, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'max_address_count_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'max_address_count': 20, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'DFC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'whitelists': [], 'human_interaction_challenge': {'is_enabled': False, 'set_http_header': None, 'recording_period_in_seconds': 15, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'interaction_threshold': 3, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'HIC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'good_bots': [{'is_enabled': False, 'description': 'Googlebot is the search bot software used by Google', 'key': '4a4c6e7b-4d89-4141-8555-ec3b22b90a73', 'name': 'Googlebot '}], 'access_rules': [], 'captchas': []}
+
  + defined_tags +
complex
+
success +
A key-value pair with a defined schema that restricts the values of tags. These predefined keys are scoped to namespaces.
+
+
Sample:
+
{'example_namespace': {'example_key': 'example_value'}}
+
  + freeform_tags +
complex
+
success +
A simple key-value pair without any defined schema.
+
+
Sample:
+
{'example_freeform_key': 'example_freeform_value'}
+
  + time_created +
str
+
success +
The date and time the policy was created, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2019-03-22 13:02:55.563000
+
  + policy_config +
complex
+
success +
The policy_config of the WaasPolicy.
+
+
Sample:
+
{'certificate_id': None, 'is_https_enabled': False, 'is_https_forced': False}
+
  + cname +
str
+
success +
The CNAME record to add to your DNS configuration to route traffic for the domain, and all additional domains, through the WAF.
+
+
Sample:
+
www-exampledomain-com.b.waas.oci.oraclecloud.net
+
  + additional_domains +
list
+
success +
An array of additional domains for this web application.
+
+
Sample:
+
['www.exampledomain1.com', 'www.exampledomain2.com']
+
  + id +
str
+
success +
The OCID of the WAAS policy.
+
+
Sample:
+
ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_policy_module.rst b/docs/modules/oci_waas_policy_module.rst new file mode 100644 index 0000000..9611b96 --- /dev/null +++ b/docs/modules/oci_waas_policy_module.rst @@ -0,0 +1,2289 @@ +:source: cloud/oracle/oci_waas_policy.py + +:orphan: + +.. _oci_waas_policy_module: + + +oci_waas_policy - Manage WAAS policies in OCI ++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module allows the user to create, delete and update WAAS policies in OCI. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ additional_domains +
list
+ +
An array of additional domains for the specified web application.
+
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ compartment_id +
str
+ +
The OCID of the compartment.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ defined_tags + + +
Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/resourcetags.htm.
+
+ display_name +
str
+ +
A user-friendly name for the WAAS policy. The name is can be changed and does not need to be unique.
+

aliases: name
+
+ domain +
str
+ +
The web application domain that the WAAS policy protects.
+
+ force_create +
bool
+
    Choices: +
  • no ←
  • +
  • yes
  • +
+
+
Whether to attempt non-idempotent creation of a resource. By default, create resource is an idempotent operation, and doesn't create the resource if it already exists. Setting this option to true, forcefully creates a copy of the resource, even if it already exists.This option is mutually exclusive with key_by.
+
+ freeform_tags + + +
Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/resourcetags.htm.
+
+ key_by + + +
The list of comma-separated attributes of this resource which should be used to uniquely identify an instance of the resource. By default, all the attributes of a resource except freeform_tags are used to uniquely identify a resource.
+
+ origins +
dict
+ +
A map of host to origin for the web application. The key should be a customer friendly name for the host, ex. primary, secondary, etc.
+
+ http_port + + +
The HTTP port on the origin that the web application listens on. If unspecified, defaults to 80.
+
+ custom_headers + + +
A list of HTTP headers to forward to your origin.
+
+ name + + +
The name of the header.
+
+ value + + +
The value of the header.
+
+ https_port + + +
The HTTPS port on the origin that the web application listens on. If unspecified, defaults to 443.
+
+ uri + + +
The URI of the origin. Does not support paths. Port numbers should be specified in the http_port and https_port fields.
+
+ policy_config +
dict
+ +
Config for the WAAS policy.
+
+ certificate_id + + +
The OCID of the SSL certificate to use if HTTPS is supported.
+
+ is_https_enabled + + Default:
no
+
+
Enable or disable HTTPS support. If true, a certificateId is required.
+
+ is_https_forced + + Default:
no
+
+
Force HTTP to HTTPS redirection.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ state + +
    Choices: +
  • present ←
  • +
  • absent
  • +
+
+
Create or update a WAAS policy with state=present. Use state=absent to delete a WAAS policy.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ waas_policy_id + + +
The OCID of the WAAS policy. Required when deleting a WAAS policy with state=absent or updating a WAAS policy with state=present. This option is mutually exclusive with compartment_id.
+

aliases: id
+
+ waf_config +
dict
+ +
The WAF config for the WAAS policy.
+
+ origin + + +
The key in the map of origins referencing the origin used for the Web Application Firewall. The origin must already be included in Origins. Required when creating the WafConfig resource, but not on update.
+
+ protection_rules + + +
A list of the protection rules and their details.
+
+ action + + Default:
no
+
+
The action to take when the traffic is detected as malicious.
+
+ description + + +
The description of the protection rule.
+
+ key + + +
The unique key of the protection rule.
+
+ mod_security_rule_ids + + +
The list of the ModSecurity rule IDs that apply to this protection rule.
+
+ labels + + +
The list of labels for the protection rule.
+
+ exclusions + + +
The exclusions of this ProtectionRule.
+
+ exclusions + + +
The exclusions of this ProtectionRuleExclusion.
+
+ target + +
    Choices: +
  • REQUEST_COOKIES
  • +
  • REQUEST_COOKIE_NAMES
  • +
  • ARGS
  • +
  • ARGS_NAMES
  • +
+
+
The target of the exclusion.
+
+ name + + +
The name of the protection rule.
+
+ address_rate_limiting + + +
The IP address rate limiting settings used to limit the number of requests from an address.
+
+ allowed_rate_per_address + + Default:
1
+
+
The number of allowed requests per second from one IP address.
+
+ is_enabled + + +
Enables or disables the address rate limiting Web Application Firewall feature.
+
+ block_response_code + + Default:
503
+
+
The response status code returned when a request is blocked.
+
+ max_delayed_count_per_address + + Default:
10
+
+
The maximum number of requests allowed to be queued before subsequent requests are dropped.
+
+ js_challenge + + +
The JavaScript challenge settings. Used to challenge requests with a JavaScript challenge and take the action if a browser has no JavaScript support in order to block bots.
+
+ is_enabled +
required
+ +
Enables or disables the JavaScript challenge Web Application Firewall feature.
+
+ set_http_header + + +
Adds an additional HTTP header to requests that fail the challenge before being passed to the origin. Only applicable when action=DETECT.
+
+ name + + +
The name of the header.
+
+ value + + +
The value of the header.
+
+ failure_threshold + + Default:
10
+
+
The number of failed requests before taking action.
+
+ action + +
    Choices: +
  • DETECT ←
  • +
  • BLOCK
  • +
+
+
The action to take against requests from detected bots.
+
+ action_expiration_in_seconds + + Default:
60
+
+
The number of seconds between challenges from the same IP address.
+
+ challenge_settings + + +
The challenge settings.
+
+ block_error_page_message + + Default:
Access to the website is blocked.
+
+
The message to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ captcha_footer + + Default:
Enter the letters and numbers as they are shown in image above.
+
+
The text to show in the footer when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ block_error_page_code + + Default:
403
+
+
The error code to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ block_action + +
    Choices: +
  • SET_RESPONSE_CODE
  • +
  • SHOW_ERROR_PAGE ←
  • +
  • SHOW_CAPTCHA
  • +
+
+
The method used to block requests that fail the challenge if action=BLOCK.
+
+ captcha_title + + Default:
Are you human?
+
+
The title used when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ captcha_header + + Default:
We have detected an increased number of attempts to access this webapp. To help us keep this webapp secure, please let us know that you are not a robot by entering the text from captcha below.
+
+
The text to show in the header when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ block_response_code + + Default:
403
+
+
The response status code to return when action=BLOCK, block_action=SET_RESPONSE_CODE, and the request is blocked.
+
+ block_error_page_description + + Default:
Access blocked by website owner. Please contact support.
+
+
The description text to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ captcha_submit_label + + Default:
Yes, I am human.
+
+
The text to show on the label of the CAPTCHA challenge submit button when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ device_fingerprint_challenge + + +
The device fingerprint challenge settings. Used to detect unique devices based on the device fingerprint information collected in order to block bots.
+
+ is_enabled + + +
Enables or disables the device fingerprint challenge Web Application Firewall feature.
+
+ failure_threshold_expiration_in_seconds + + Default:
60
+
+
The number of seconds before the failure threshold resets.
+
+ action_expiration_in_seconds + + Default:
60
+
+
The number of seconds between challenges for the same IP address.
+
+ max_address_count_expiration_in_seconds + + Default:
60
+
+
The number of seconds before the maximum addresses count resets.
+
+ failure_threshold + + Default:
10
+
+
The number of failed requests allowed before taking action.
+
+ action + +
    Choices: +
  • DETECT ←
  • +
  • BLOCK
  • +
+
+
The action to take on requests from detected bots.
+
+ max_address_count + + Default:
20
+
+
The maximum number of IP addresses permitted with the same device fingerprint.
+
+ challenge_settings + + +
The challenge settings.
+
+ block_error_page_message + + Default:
Access to the website is blocked.
+
+
The message to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ captcha_footer + + Default:
Enter the letters and numbers as they are shown in image above.
+
+
The text to show in the footer when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ block_error_page_code + + Default:
403
+
+
The error code to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ block_action + +
    Choices: +
  • SET_RESPONSE_CODE
  • +
  • SHOW_ERROR_PAGE ←
  • +
  • SHOW_CAPTCHA
  • +
+
+
The method used to block requests that fail the challenge if action=BLOCK.
+
+ captcha_title + + Default:
Are you human?
+
+
The title used when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ captcha_header + + Default:
We have detected an increased number of attempts to access this webapp. To help us keep this webapp secure, please let us know that you are not a robot by entering the text from captcha below.
+
+
The text to show in the header when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ block_response_code + + Default:
403
+
+
The response status code to return when action=BLOCK, block_action=SET_RESPONSE_CODE, and the request is blocked.
+
+ block_error_page_description + + Default:
Access blocked by website owner. Please contact support.
+
+
The description text to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ captcha_submit_label + + Default:
Yes, I am human.
+
+
The text to show on the label of the CAPTCHA challenge submit button when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ whitelists + + +
A list of IP addresses that bypass the Web Application Firewall.
+
+ addresses +
required
+ +
A set of IP addresses or CIDR notations to include in the whitelist.
+
+ name +
required
+ +
The unique name of the whitelist.
+
+ human_interaction_challenge + + +
The human interaction challenge settings. Used to look for natural human interactions such as mouse movements, time on site, and page scrolling to identify bots.
+
+ is_enabled + + +
Enables or disables the human interaction challenge Web Application Firewall feature.
+
+ set_http_header + + +
Adds an additional HTTP header to requests that fail the challenge before being passed to the origin. Only applicable when action=DETECT.
+
+ name + + +
The name of the header.
+
+ value + + +
The value of the header.
+
+ recording_period_in_seconds + + Default:
15
+
+
The number of seconds to record the interactions from the user.
+
+ failure_threshold_expiration_in_seconds + + Default:
60
+
+
The number of seconds before the failure threshold resets.
+
+ action_expiration_in_seconds + + Default:
60
+
+
The number of seconds between challenges for the same IP address.
+
+ failure_threshold + + Default:
10
+
+
The number of failed requests allowed before taking action.
+
+ action + +
    Choices: +
  • DETECT ←
  • +
  • BLOCK
  • +
+
+
The action to take on requests from detected bots.
+
+ interaction_threshold + + Default:
3
+
+
The number of interactions required to pass the challenge.
+
+ challenge_settings + + +
The challenge settings.
+
+ block_error_page_message + + Default:
Access to the website is blocked.
+
+
The message to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ captcha_footer + + Default:
Enter the letters and numbers as they are shown in image above.
+
+
The text to show in the footer when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ block_error_page_code + + Default:
403
+
+
The error code to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ block_action + +
    Choices: +
  • SET_RESPONSE_CODE
  • +
  • SHOW_ERROR_PAGE ←
  • +
  • SHOW_CAPTCHA
  • +
+
+
The method used to block requests that fail the challenge if action=BLOCK.
+
+ captcha_title + + Default:
Are you human?
+
+
The title used when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ captcha_header + + Default:
We have detected an increased number of attempts to access this webapp. To help us keep this webapp secure, please let us know that you are not a robot by entering the text from captcha below.
+
+
The text to show in the header when showing a CAPTCHA challenge when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ block_response_code + + Default:
403
+
+
The response status code to return when action=BLOCK, block_action=SET_RESPONSE_CODE, and the request is blocked.
+
+ block_error_page_description + + Default:
Access blocked by website owner. Please contact support.
+
+
The description text to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the request is blocked.
+
+ captcha_submit_label + + Default:
Yes, I am human.
+
+
The text to show on the label of the CAPTCHA challenge submit button when action=BLOCK, block_action=SHOW_CAPTCHA, and the request is blocked.
+
+ good_bots + + +
A list of bots allowed to access the web application.
+
+ is_enabled + + +
Enables or disables the bot.
+
+ description + + +
The description of the bot.
+
+ key + + +
The unique key for the bot.
+
+ name + + +
The bot name.
+
+ access_rules + + +
The access rules applied to the Web Application Firewall. Used for defining custom access policies with the combination of ALLOW, DETECT, and BLOCK rules, based on different criteria.
+
+ block_error_page_message + + Default:
Access to the website is blocked.
+
+
The message to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the access criteria are met.
+
+ name + + +
The unique name of the access rule.
+
+ block_error_page_code + + Default:
Access rules
+
+
The error code to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the access criteria are met.
+
+ block_action + +
    Choices: +
  • SET_RESPONSE_CODE ←
  • +
  • SHOW_ERROR_PAGE
  • +
+
+
The method used to block requests if action=BLOCK and the access criteria are met.
+
+ criteria + + +
The list of access rule criteria.
+
+ condition +
required
+ +
The criteria the access rule uses to determine if action should be taken on a request.
+
+ value +
required
+
    Choices: +
  • URL_IS
  • +
  • URL_IS_NOT
  • +
  • URL_STARTS_WITH
  • +
  • URL_PART_ENDS_WITH
  • +
  • URL_PART_CONTAINS
  • +
  • URL_REGEX
  • +
  • IP_IS
  • +
  • IP_IS_NOT
  • +
  • HTTP_HEADER_CONTAINS
  • +
  • COUNTRY_IS
  • +
  • COUNTRY_IS_NOT
  • +
  • USER_AGENT_IS
  • +
  • USER_AGENT_IS_NOT
  • +
+
+
The criteria value.
+
+ action + + Default:
ALLOW
+
+
The action to take when the access criteria are met for a rule.
+
+ block_response_code + + Default:
403
+
+
The response status code to return when action=BLOCK, block_action=SET_RESPONSE_CODE, and the access criteria are met.
+
+ block_error_page_description + + Default:
Access blocked by website owner. Please contact support.
+
+
The description text to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the access criteria are met.
+
+ protection_settings + + +
The settings to apply to protection rules.
+
+ media_types + + Default:
[u'text/html', u'text/plain', u'text/xml']
+
+
The list of media types to allow for inspection, if is_response_inspected=True. Only responses with MIME types in this list will be inspected.
+
+ block_error_page_message + + Default:
Access to the website is blocked.
+
+
The message to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the traffic is detected as malicious by a protection rule.
+
+ max_total_name_length_of_arguments + + Default:
64000
+
+
The maximum length allowed for the sum of all argument names, in characters.
+
+ recommendations_period_in_days + + Default:
10
+
+
The length of time to analyze traffic, in days. After the analysis period, WafRecommendations will be populated.
+
+ block_error_page_code + + Default:
403
+
+
The error code to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the traffic is detected as malicious by a protection rule.
+
+ max_response_size_in_ki_b + + Default:
1024
+
+
The maximum response size to be fully inspected, in binary kilobytes (KiB). Anything over this limit will be partially inspected.
+
+ block_action + +
    Choices: +
  • SHOW_ERROR_PAGE
  • +
  • SET_RESPONSE_CODE ←
  • +
+
+
If action=BLOCK, this specifies how the traffic is blocked when detected as malicious by a protection rule.
+
+ max_argument_count + + Default:
255
+
+
The maximum number of arguments allowed to be passed to your application before an action is taken.
+
+ max_name_length_per_argument + + Default:
400
+
+
The maximum length allowed for each argument name, in characters.
+
+ is_response_inspected + + Default:
no
+
+
Inspects the response body of origin responses. Can be used to detect leakage of sensitive data.
+
+ block_response_code + + Default:
403
+
+
The response code returned when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the traffic is detected as malicious by a protection rule.
+
+ allowed_http_methods + +
    Choices: +
  • OPTIONS ←
  • +
  • GET ←
  • +
  • HEAD ←
  • +
  • POST ←
  • +
  • PUT
  • +
  • DELETE
  • +
  • TRACE
  • +
  • CONNECT
  • +
  • PATCH
  • +
  • PROPFIND
  • +
+ Default:
[u'OPTIONS', u'GET', u'HEAD', u'POST']
+
+
The list of allowed HTTP methods. If unspecified, default to [OPTIONS, GET, HEAD, POST].
+
+ block_error_page_description + + Default:
Access blocked by website owner. Please contact support.
+
+
The description text to show on the error page when action=BLOCK, block_action=SHOW_ERROR_PAGE, and the traffic is detected as malicious by a protection rule.
+
+ captchas + + +
A list of CAPTCHA challenge settings. These are used to challenge requests with a CAPTCHA to block bots.
+
+ submit_label +
required
+ +
The text to show on the label of the CAPTCHA challenge submit button.
+
+ header_text + + Default:
We have detected an increased number of attempts to access this website. To help us keep this site secure, please let us know that you are not a robot by entering the text from the image below.
+
+
The text to show in the header when showing a CAPTCHA challenge.
+
+ title +
required
+ +
The title used when displaying a CAPTCHA challenge.
+
+ url +
required
+ +
The unique URL path at which to show the CAPTCHA challenge.
+
+ session_expiration_in_seconds +
required
+ +
The amount of time before the CAPTCHA expires, in seconds.
+
+ footer_text + + Default:
Enter the letters and numbers as they are shown in the image above.
+
+
The text to show in the footer when showing a CAPTCHA challenge.
+
+ failure_message +
required
+ +
The text to show when incorrect CAPTCHA text is entered.
+
+ threat_feeds + + +
A list of threat intelligence feeds and the actions to apply to known malicious traffic based on internet intelligence.
+
+ action + +
    Choices: +
  • no ←
  • +
  • DETECT
  • +
  • BLOCK
  • +
+ Default:
no
+
+
The action to take when traffic is flagged as malicious by data from the threat intelligence feed.
+
+ description + + +
The description of the threat intelligence feed.
+
+ key + + +
The unique key of the threat intelligence feed.
+
+ name + + +
The name of the threat intelligence feed.
+
+ wait +
bool
+
    Choices: +
  • no
  • +
  • yes ←
  • +
+
+
Whether to wait for create or delete operation to complete.
+
+ wait_timeout + + Default:
1200
+
+
Time, in seconds, to wait when wait=yes.
+
+ wait_until + + +
The lifecycle state to wait for the resource to transition into when wait=yes. By default, when wait=yes, we wait for the resource to get into ACTIVE/ATTACHED/AVAILABLE/PROVISIONED/ RUNNING applicable lifecycle state during create operation & to get into DELETED/DETACHED/ TERMINATED lifecycle state during delete operation.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Create a WAAS policy + oci_waas_policy: + cidr_block: '10.0.0.0/16' + compartment_id: 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx' + display_name: my_vcn + dns_label: ansiblevcn + + - name: Updates the specified VCN's display name + oci_vcn: + vcn_id: ocid1.vcn.oc1.phx.xxxxxEXAMPLExxxxx + display_name: ansible_vcn + + - name: Delete the specified VCN + oci_vcn: + vcn_id: ocid1.vcn.oc1.phx.xxxxxEXAMPLExxxxx + state: absent + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_policy +
complex
+
on success +
List of waas policies
+
+
Sample:
+
[{'lifecycle_state': 'ACTIVE', 'domain': 'www.example.com', 'display_name': 'ansible_test_waas_policy', 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'origins': {'LBaaS': {'http_port': 80, 'custom_headers': [], 'https_port': 443, 'uri': '1.2.3.4'}}, 'waf_config': {'origin': 'LBaaS', 'protection_rules': [{'action': 'OFF', 'description': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from IE', 'key': '941340', 'mod_security_rule_ids': ['941340'], 'labels': ['OWASP', 'OWASP-2017', 'CRS3', 'WASCTC', 'PCI', 'HTTP', 'A2', 'A2-2017', 'XSS', 'Cross-Site Scripting'], 'exclusions': [], 'name': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer'}], 'address_rate_limiting': {'allowed_rate_per_address': 1, 'is_enabled': False, 'block_response_code': 503, 'max_delayed_count_per_address': 10}, 'js_challenge': {'is_enabled': False, 'set_http_header': {'name': 'x-jsc-alerts', 'value': '{failed_amount}'}, 'failure_threshold': 10, 'action': 'DETECT', 'action_expiration_in_seconds': 60, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'JSC-403', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'device_fingerprint_challenge': {'is_enabled': False, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'max_address_count_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'max_address_count': 20, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'DFC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'whitelists': [], 'human_interaction_challenge': {'is_enabled': False, 'set_http_header': None, 'recording_period_in_seconds': 15, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'interaction_threshold': 3, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'HIC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'good_bots': [{'is_enabled': False, 'description': 'Googlebot is the search bot software used by Google.', 'key': '4a4c6e7b-4d89-4141-8555-ec3b22b90a73', 'name': 'Googlebot '}], 'access_rules': [], 'captchas': []}, 'defined_tags': {'example_namespace': {'example_key': 'example_value'}}, 'freeform_tags': {'example_freeform_key': 'example_freeform_value'}, 'time_created': '2019-03-22T13:02:55.563000+00:00', 'policy_config': {'certificate_id': None, 'is_https_enabled': False, 'is_https_forced': False}, 'cname': 'www-exampledomain-com.b.waas.oci.oraclecloud.net', 'additional_domains': ['www.exampledomain1.com', 'www.exampledomain2.com'], 'id': 'ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx'}]
+
  + lifecycle_state +
str
+
success +
The current lifecycle state of the WAAS policy.
+
+
Sample:
+
ACTIVE
+
  + domain +
str
+
success +
The web application domain that the WAAS policy protects.
+
+
Sample:
+
www.exampledomain.com
+
  + display_name +
str
+
success +
The user-friendly name of the WAAS policy.
+
+
Sample:
+
examplewaaspolicy1
+
  + compartment_id +
str
+
success +
The OCID of the WAAS policy's compartment.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+
  + origins +
complex
+
success +
A map of host to origin for the web application.
+
+
Sample:
+
{'LBaaS': {'http_port': 80, 'custom_headers': [], 'https_port': 443, 'uri': '1.2.3.4'}}
+
  + waf_config +
complex
+
success +
The waf_config of this WaasPolicy.
+
+
Sample:
+
{'origin': 'LBaaS', 'protection_rules': [{'action': 'OFF', 'description': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from IE', 'key': '941340', 'mod_security_rule_ids': ['941340'], 'labels': ['OWASP', 'OWASP-2017', 'CRS3', 'WASCTC', 'PCI', 'HTTP', 'A2', 'A2-2017', 'XSS', 'Cross-Site Scripting'], 'exclusions': [], 'name': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer'}], 'address_rate_limiting': {'allowed_rate_per_address': 1, 'is_enabled': False, 'block_response_code': 503, 'max_delayed_count_per_address': 10}, 'js_challenge': {'is_enabled': False, 'set_http_header': {'name': 'x-jsc-alerts', 'value': '{failed_amount}'}, 'failure_threshold': 10, 'action': 'DETECT', 'action_expiration_in_seconds': 60, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'JSC-403', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'device_fingerprint_challenge': {'is_enabled': False, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'max_address_count_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'max_address_count': 20, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'DFC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'whitelists': [], 'human_interaction_challenge': {'is_enabled': False, 'set_http_header': None, 'recording_period_in_seconds': 15, 'failure_threshold_expiration_in_seconds': 60, 'action_expiration_in_seconds': 60, 'failure_threshold': 10, 'action': 'DETECT', 'interaction_threshold': 3, 'challenge_settings': {'block_error_page_message': 'Access to the website is blocked.', 'captcha_footer': 'Enter the letters and numbers as they are shown in image above.', 'block_error_page_code': 'HIC', 'block_action': 'SHOW_ERROR_PAGE', 'captcha_title': 'Are you human?', 'captcha_header': 'We have detected an increased number of attempts to access this website.', 'block_response_code': 403, 'block_error_page_description': 'Access blocked by website owner. Please contact support.', 'captcha_submit_label': 'Yes, I am human.'}}, 'good_bots': [{'is_enabled': False, 'description': 'Googlebot is the search bot software used by Google', 'key': '4a4c6e7b-4d89-4141-8555-ec3b22b90a73', 'name': 'Googlebot '}], 'access_rules': [], 'captchas': []}
+
  + defined_tags +
complex
+
success +
A key-value pair with a defined schema that restricts the values of tags. These predefined keys are scoped to namespaces.
+
+
Sample:
+
{'example_namespace': {'example_key': 'example_value'}}
+
  + freeform_tags +
complex
+
success +
A simple key-value pair without any defined schema.
+
+
Sample:
+
{'example_freeform_key': 'example_freeform_value'}
+
  + time_created +
str
+
success +
The date and time the policy was created, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2019-03-22 13:02:55.563000
+
  + policy_config +
complex
+
success +
The policy_config of the WaasPolicy.
+
+
Sample:
+
{'certificate_id': None, 'is_https_enabled': False, 'is_https_forced': False}
+
  + cname +
str
+
success +
The CNAME record to add to your DNS configuration to route traffic for the domain, and all additional domains, through the WAF.
+
+
Sample:
+
www-exampledomain-com.b.waas.oci.oraclecloud.net
+
  + additional_domains +
list
+
success +
An array of additional domains for this web application.
+
+
Sample:
+
['www.exampledomain1.com', 'www.exampledomain2.com']
+
  + id +
str
+
success +
The OCID of the WAAS policy.
+
+
Sample:
+
ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_recommendation_facts_module.rst b/docs/modules/oci_waas_recommendation_facts_module.rst new file mode 100644 index 0000000..d5b913a --- /dev/null +++ b/docs/modules/oci_waas_recommendation_facts_module.rst @@ -0,0 +1,323 @@ +:source: cloud/oracle/oci_waas_recommendation_facts.py + +:orphan: + +.. _oci_waas_recommendation_facts_module: + + +oci_waas_recommendation_facts - Retrieve details about WAAS policy recommendations. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module retrieves information of recommended Web Application Firewall protection rules for a WAAS policy. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ recommended_action +
str
+
    Choices: +
  • DETECT
  • +
  • BLOCK
  • +
+
+
A filter that matches recommended protection rules based on the selected action. If unspecified, rules with any action type are returned.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ waas_policy_id +
str

required
+ +
The OCID of the WAAS policy.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get the recommendations for a waas policy + oci_waas_recommendation_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + + - name: Get the recommendations of specific action for a waas policy + oci_waas_recommendation_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + recommended_action: DETECT + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_recommendations +
complex
+
on success +
List of recommended Web Application Firewall protection rules for a WAAS policy.
+
+
Sample:
+
[{'mod_security_rule_ids': ['941340'], 'description': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from IE', 'key': '941340', 'recommended_action': 'BLOCK', 'labels': ['OWASP', 'OWASP-2017', 'CRS3', 'WASCTC', 'PCI', 'HTTP', 'A2', 'A2-2017', 'XSS', 'Cross-Site Scripting'], 'name': 'Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer'}]
+
  + mod_security_rule_ids +
list
+
success +
The list of the ModSecurity rule IDs associated with the protection rule.
+
+
Sample:
+
['941340']
+
  + description +
str
+
success +
The description of the recommended protection rule.
+
+
Sample:
+
Cross-Site Scripting (XSS) Attempt: XSS Filters from IE
+
  + key +
str
+
success +
The unique key for the recommended protection rule.
+
+
Sample:
+
941340
+
  + recommended_action +
str
+
success +
The recommended action to apply to the protection rule.
+
+
Sample:
+
BLOCK
+
  + labels +
list
+
success +
The list of labels for the recommended protection rule.
+
+
Sample:
+
['OWASP', 'OWASP-2017', 'CRS3', 'WASCTC', 'PCI', 'HTTP', 'A2', 'A2-2017', 'XSS', 'Cross-Site Scripting']
+
  + name +
str
+
success +
The name of the recommended protection rule.
+
+
Sample:
+
Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_work_request_facts_module.rst b/docs/modules/oci_waas_work_request_facts_module.rst new file mode 100644 index 0000000..9c71a97 --- /dev/null +++ b/docs/modules/oci_waas_work_request_facts_module.rst @@ -0,0 +1,435 @@ +:source: cloud/oracle/oci_waas_work_request_facts.py + +:orphan: + +.. _oci_waas_work_request_facts_module: + + +oci_waas_work_request_facts - Retrieve details about WAAS policy work requests. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module retrieves information of a specific work request or lists all the work requests in the given WAAS policy and compartment. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ compartment_id +
str
+ +
The OCID of the compartment.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ sort_by +
str
+
    Choices: +
  • id
  • +
  • status
  • +
  • timeAccepted
  • +
  • timeStarted
  • +
  • timeFinished
  • +
  • operationType
  • +
+
+
The value by which work requests are sorted in a paginated 'List' call. If unspecified, defaults to timeAccepted.
+
+ sort_order +
str
+
    Choices: +
  • ASC
  • +
  • DESC
  • +
+
+
The order in which to sort the results.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ waas_policy_id +
str
+ +
The OCID of the WAAS policy.
+
+ work_request_id +
str
+ +
The OCID of the work request. Required to retrieve a specific work request.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Get all the work requests for a waas policy in a compartment + oci_waas_work_request_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + + - name: Get all the work requests for a waas policy in a compartment sorted by timeFinished + oci_waas_work_request_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + sort_by: timeFinished + + - name: Get a specific waas work request using its OCID + oci_waas_work_request_facts: + work_request_id: ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_work_requests +
complex
+
on success +
List of work requests
+
+
Sample:
+
[{'status': 'IN_PROGRESS', 'time_finished': None, 'errors': [], 'logs': [{'timestamp': '2019-04-10T18:46:05.663000+00:00', 'message': 'addWhitelistOp: start'}, {'timestamp': '2019-04-10T18:46:05.663000+00:00', 'message': 'addWhitelistOp: finished (45% of request completed)'}, {'timestamp': '2019-04-10T18:46:05.403000+00:00', 'message': 'updateProtectionSettingsOp: start'}], 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'operation_type': 'CREATE_WAAS_POLICY', 'percent_complete': 45, 'time_accepted': '2019-04-10T18:45:45.044000+00:00', 'id': 'ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx', 'resources': [{'entity_uri': '/20181116/waasPolicies/ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx', 'identifier': 'ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx', 'action_type': 'CREATED', 'entity_type': 'waas'}], 'time_started': '2019-04-10T18:45:49+00:00'}]
+
  + status +
str
+
success +
The current status of the work request.
+
+
Sample:
+
IN_PROGRESS
+
  + time_finished +
str
+
success +
The date and time the work request was fulfilled or terminated, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2019-03-22 13:02:59.563000
+
  + errors +
list
+
success +
The list of errors that occurred while fulfilling the work request.
+
+
  + logs +
list
+
success +
The list of log entries from the work request workflow.
+
+
Sample:
+
[{'timestamp': '2019-04-10T19:31:57.364000+00:00', 'message': 'Work request complete'}, {'timestamp': '2019-04-10T19:31:57.360000+00:00', 'message': 'PersistWaasOp: start (100% of request completed)'}, {'timestamp': '2019-04-10T19:31:57.261000+00:00', 'message': 'Starting Work Request'}]
+
  + compartment_id +
str
+
success +
The OCID of the compartment that contains the work request.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+
  + operation_type +
str
+
success +
A description of the operation requested by the work request.
+
+
Sample:
+
CREATE_WAAS_POLICY
+
  + percent_complete +
int
+
success +
The percentage of work completed by the work request.
+
+
Sample:
+
50
+
  + time_accepted +
str
+
success +
The date and time the work request was created, in the format defined by RFC3339.
+
+
Sample:
+
2019-03-22 13:02:55.563000
+
  + id +
str
+
success +
The OCID of the work request.
+
+
Sample:
+
ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx
+
  + resources +
str
+
success +
The resources being used to complete the work request operation.
+
+
Sample:
+
[{'entity_uri': '/20181116/waasPolicies/ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx', 'identifier': 'ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx', 'action_type': 'CREATED', 'entity_type': 'waas'}]
+
  + time_started +
str
+
success +
The date and time the work request moved from the ACCEPTED state to the IN_PROGRESS state, expressed in RFC 3339 timestamp format.
+
+
Sample:
+
2019-03-22 13:02:56.563000
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/modules/oci_waas_work_request_module.rst b/docs/modules/oci_waas_work_request_module.rst new file mode 100644 index 0000000..00df858 --- /dev/null +++ b/docs/modules/oci_waas_work_request_module.rst @@ -0,0 +1,415 @@ +:source: cloud/oracle/oci_waas_work_request.py + +:orphan: + +.. _oci_waas_work_request_module: + + +oci_waas_work_request - Manage WAAS policy work requests in OCI ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. versionadded:: 2.5 + +.. contents:: + :local: + :depth: 2 + + +Synopsis +-------- +- This module allows the user to cancel a WAAS policy work request in OCI. + + + +Requirements +~~~~~~~~~~~~ +The below requirements are needed on the host that executes this module. + +- python >= 2.6 +- Python SDK for Oracle Cloud Infrastructure https://oracle-cloud-infrastructure-python-sdk.readthedocs.io + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+ api_user + + +
The OCID of the user, on whose behalf, OCI APIs are invoked. If not set, then the value of the OCI_USER_OCID environment variable, if any, is used. This option is required if the user is not specified through a configuration file (See config_file_location). To get the user's OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_fingerprint + + +
Fingerprint for the key pair being used. If not set, then the value of the OCI_USER_FINGERPRINT environment variable, if any, is used. This option is required if the key fingerprint is not specified through a configuration file (See config_file_location). To get the key pair's fingerprint value please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm.
+
+ api_user_key_file + + +
Full path and filename of the private key (in PEM format). If not set, then the value of the OCI_USER_KEY_FILE variable, if any, is used. This option is required if the private key is not specified through a configuration file (See config_file_location). If the key is encrypted with a pass-phrase, the api_user_key_pass_phrase option must also be provided.
+
+ api_user_key_pass_phrase + + +
Passphrase used by the key referenced in api_user_key_file, if it is encrypted. If not set, then the value of the OCI_USER_KEY_PASS_PHRASE variable, if any, is used. This option is required if the key passphrase is not specified through a configuration file (See config_file_location).
+
+ auth_type + +
    Choices: +
  • api_key ←
  • +
  • instance_principal
  • +
+
+
The type of authentication to use for making API requests. By default auth_type="api_key" based authentication is performed and the API key (see api_user_key_file) in your config file will be used. If this 'auth_type' module option is not specified, the value of the OCI_ANSIBLE_AUTH_TYPE, if any, is used. Use auth_type="instance_principal" to use instance principal based authentication when running ansible playbooks within an OCI compute instance.
+
+ config_file_location + + +
Path to configuration file. If not set then the value of the OCI_CONFIG_FILE environment variable, if any, is used. Otherwise, defaults to ~/.oci/config.
+
+ config_profile_name + + +
The profile to load from the config file referenced by config_file_location. If not set, then the value of the OCI_CONFIG_PROFILE environment variable, if any, is used. Otherwise, defaults to the "DEFAULT" profile in config_file_location.
+
+ region + + +
The Oracle Cloud Infrastructure region to use for all OCI API requests. If not set, then the value of the OCI_REGION variable, if any, is used. This option is required if the region is not specified through a configuration file (See config_file_location). Please refer to https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm for more information on OCI regions.
+
+ state + +
    Choices: +
  • cancelled ←
  • +
+
+
Cancel a WAAS work request with state=cancelled.
+
+ tenancy + + +
OCID of your tenancy. If not set, then the value of the OCI_TENANCY variable, if any, is used. This option is required if the tenancy OCID is not specified through a configuration file (See config_file_location). To get the tenancy OCID, please refer https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm
+
+ wait +
bool
+
    Choices: +
  • no
  • +
  • yes ←
  • +
+
+
Whether to wait for create or delete operation to complete.
+
+ wait_timeout + + Default:
1200
+
+
Time, in seconds, to wait when wait=yes.
+
+ wait_until + + +
The lifecycle state to wait for the resource to transition into when wait=yes. By default, when wait=yes, we wait for the resource to get into ACTIVE/ATTACHED/AVAILABLE/PROVISIONED/ RUNNING applicable lifecycle state during create operation & to get into DELETED/DETACHED/ TERMINATED lifecycle state during delete operation.
+
+ work_request_id +
str

required
+ +
The OCID of the work request. Required to retrieve a specific work request.
+
+
+ + +Notes +----- + +.. note:: + - For OCI python sdk configuration, please refer to https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/configuration.html + + +Examples +-------- + +.. code-block:: yaml+jinja + + + - name: Cancel a waas work request + oci_waas_work_request: + work_request_id: "ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx" + state: cancelled + + - name: Cancel a waas work request without explicitly stating the state as it is default + oci_waas_work_request: + work_request_id: "ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx" + + + + +Return Values +------------- +Common return values are documented :ref:`here `, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+ waas_work_request +
complex
+
on success +
Information about the WAAS work request.
+
+
Sample:
+
{'status': 'CANCELLED', 'time_finished': None, 'errors': [], 'logs': [], 'compartment_id': 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx', 'operation_type': 'UPDATE_WAAS_POLICY', 'percent_complete': 0, 'time_accepted': '2019-03-22T13:02:55.563000+00:00', 'resources': [], 'time_started': None}
+
  + status +
str
+
success +
The current status of the work request.
+
+
Sample:
+
CANCELLED
+
  + time_finished +
str
+
success +
The date and time the work request was fulfilled or terminated, expressed in RFC 3339 timestamp format.
+
+
  + errors +
list
+
success +
The list of errors that occurred while fulfilling the work request.
+
+
  + logs +
list
+
success +
The list of log entries from the work request workflow.
+
+
  + compartment_id +
str
+
success +
The OCID of the compartment that contains the work request.
+
+
Sample:
+
ocid1.compartment.oc1..xxxxxEXAMPLExxxxx
+
  + operation_type +
str
+
success +
A description of the operation requested by the work request.
+
+
Sample:
+
UPDATE_WAAS_POLICY
+
  + percent_complete +
int
+
success +
The percentage of work completed by the work request.
+
+
  + time_accepted +
str
+
success +
The date and time the work request was created, in the format defined by RFC3339.
+
+
Sample:
+
2019-03-22 13:02:55.563000
+
  + id +
str
+
success +
The OCID of the work request.
+
+
Sample:
+
ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx
+
  + resources +
str
+
success +
The resources being used to complete the work request operation.
+
+
  + time_started +
str
+
success +
The date and time the work request moved from the ACCEPTED state to the IN_PROGRESS state, expressed in RFC 3339 timestamp format.
+
+
+

+ + +Status +------ + + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + +This module is flagged as **preview** which means that it is not guaranteed to have a backwards compatible interface. + + + +Author +~~~~~~ + +- Manoj Meda (@manojmeda) + + +.. hint:: + If you notice any issues in this documentation you can `edit this document `_ to improve it. diff --git a/docs/technical-overview.md b/docs/technical-overview.md index 1179a59..3573457 100644 --- a/docs/technical-overview.md +++ b/docs/technical-overview.md @@ -41,7 +41,7 @@ In the current version of the OCI Ansible modules, the following Services are su - Compute - Container Engine for Kubernetes Service (OKE) - Database (including support for Autonomous Transaction Processing and Autonomous Data Warehouse Services) -- Domain Name System (DNS) +- Edge Services (DNS, WAF) - IAM - Load Balancing - Networking diff --git a/install.py b/install.py index 61aa61a..f4c3897 100755 --- a/install.py +++ b/install.py @@ -38,7 +38,7 @@ debug = False -MIN_OCI_PYTHON_SDK_REQUIRED = "2.1.3" +MIN_OCI_PYTHON_SDK_REQUIRED = "2.1.7" def parse_cli_args(): diff --git a/inventory-script/oci_inventory.py b/inventory-script/oci_inventory.py index dfd48f7..16a2cc0 100755 --- a/inventory-script/oci_inventory.py +++ b/inventory-script/oci_inventory.py @@ -226,7 +226,7 @@ except ImportError: HAS_OCI_PY_SDK = False -__version__ = "1.7.0" +__version__ = "1.8.0" def _get_retry_strategy(): diff --git a/library/oci_app_catalog_listing_resource_version_facts.py b/library/oci_app_catalog_listing_resource_version_facts.py index eddd1a2..49757f1 100644 --- a/library/oci_app_catalog_listing_resource_version_facts.py +++ b/library/oci_app_catalog_listing_resource_version_facts.py @@ -71,7 +71,7 @@ description: List of shapes compatible with this resource. returned: always type: list - sample: ["VM.Standard1.1", "VM.Standard1.2"] + sample: ["VM.Standard2.1", "VM.Standard2.2"] listing_id: description: The OCID of the listing this resource version belongs to. returned: always @@ -100,8 +100,8 @@ "us-phoenix-1" ], "compatible_shapes": [ - "VM.Standard1.1", - "VM.Standard1.2", + "VM.Standard2.1", + "VM.Standard2.2", ], "listing_id": "ocid1.appcataloglisting.oc1..xxxxxEXAMPLExxxxx", "listing_resource_id": "ocid1.image.oc1..xxxxxEXAMPLExxxxx", diff --git a/library/oci_bucket_facts.py b/library/oci_bucket_facts.py index f59d151..08769c8 100644 --- a/library/oci_bucket_facts.py +++ b/library/oci_bucket_facts.py @@ -28,19 +28,20 @@ description: Name of the namespace from which facts of constituent buckets needs to be fetched. required: true compartment_id: - description: Identifier of the compartment from which facts of constituent buckets needs to be fetched. \ + description: Identifier of the compartment from which facts of constituent buckets needs to be fetched. Required to get details of all buckets in a specified namespace and compartment. - required: false name: description: Name of the bucket. Required to fetch details of a specific bucket. required: false aliases: [ 'bucket' ] fields: - description: Bucket summary in list of buckets includes the 'namespace', 'name', 'compartmentId', 'createdBy', - 'timeCreated', and 'etag' fields. This parameter can also include 'tags' (freeformTags and - definedTags). The only supported value of this parameter is 'tags' for now. + description: Specifies additional fields to be returned in the response. By default a response includes + the 'namespace', 'name', 'compartment_id', 'created_by', 'time_created', and 'etag' fields. + Specifying "tags" will populate the fields "freeform_tags" and "defined_tags". Specifying + "approximateSize" will populate the field "approximate_size". Specifying "approximateCount" + will populate the field "approximate_size". Any combination of the values may be provided. required: false - choices: ['tags'] + choices: ["tags", "approximateCount", "approximateSize"] type: 'list' author: "Debayan Gupta(@debayan_gupta)" extends_documentation_fragment: oracle @@ -56,11 +57,24 @@ namespace_name: 'mynamespace' compartment_id: 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx' -#Fetch facts of a specific bucket +- name: List bucket facts (including tags) + oci_bucket_facts: + namespace_name: 'mynamespace' + compartment_id: 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx' + fields: ["tags"] + +# Fetch facts of a specific bucket +- name: Fetch a bucket + oci_bucket_facts: + namespace_name: 'mynamespace' + name: 'Bucket1' + +# Fetch facts of a specific bucket (including approximate size and count) - name: Fetch a bucket oci_bucket_facts: namespace_name: 'mynamespace' name: 'Bucket1' + fields: ["approximateSize", "approximateCount"] """ RETURN = """ @@ -112,6 +126,18 @@ returned: always type: string sample: 2017-10-07T16:20:33.933000+00:00 + approximate_size: + description: The approximate total size of all objects in the bucket. \ + Size statistics are reported periodically. You will see a lag between what is displayed and \ + the actual size of the bucket. + returned: only when 'approximateSize' is specified in the 'fields' input option + type: int + approximate_count: + description: The approximate number of objects in the bucket. \ + Count statistics are reported periodically. You will see a lag between what is displayed \ + and the actual object count. + returned: only when 'approximateCount' is specified in the 'fields' input option + type: int sample: [{"compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", "created_by": "ocid1.user.oc1..xxxxxEXAMPLExxxxx", "etag": "7d48fea5-ghfc", @@ -142,27 +168,43 @@ HAS_OCI_PY_SDK = False -def list_buckets(object_storage_client, module): +def list_buckets(object_storage_client, module, get_kwargs, list_kwargs): try: namespace_name = module.params["namespace_name"] compartment_id = module.params["compartment_id"] - optional_list_method_params = ["fields"] - optional_kwargs = dict( - (param, module.params[param]) - for param in optional_list_method_params - if module.params.get(param) is not None - ) + buckets_to_return = [] buckets = oci_utils.list_all_resources( object_storage_client.list_buckets, namespace_name=namespace_name, compartment_id=compartment_id, - **optional_kwargs + **list_kwargs ) + + # if there are fields requested that are only available on the Get call + # we must individually fetch each bucket in the list + if get_kwargs: + for bucket in buckets: + buckets_to_return.append( + object_storage_client.get_bucket( + namespace_name, bucket.name, **get_kwargs + ).data + ) + else: + buckets_to_return = buckets except ServiceError as ex: module.fail_json(msg=ex.message) - return to_dict(buckets) + return to_dict(buckets_to_return) + + +def filter_to_whitelisted_arguments(argument_list, whitelist): + filtered_list = [] + for value in argument_list: + if value in whitelist: + filtered_list.append(value) + + return filtered_list def main(): @@ -172,7 +214,11 @@ def main(): namespace_name=dict(type="str", required=True), compartment_id=dict(type="str", required=False), name=dict(type="str", required=False, aliases=["bucket"]), - fields=dict(type="list", required=False, choices=["tags"]), + fields=dict( + type="list", + required=False, + choices=["tags", "approximateSize", "approximateCount"], + ), ) ) module = AnsibleModule( @@ -186,20 +232,35 @@ def main(): object_storage_client = oci_utils.create_service_client(module, ObjectStorageClient) + valid_field_values_for_list_call = ["tags"] + valid_field_values_for_get_call = ["approximateSize", "approximateCount"] + + get_kwargs = {} + list_kwargs = {} + + fields_arg_value = module.params.get("fields") + if fields_arg_value: + get_kwargs["fields"] = filter_to_whitelisted_arguments( + fields_arg_value, valid_field_values_for_get_call + ) + list_kwargs["fields"] = filter_to_whitelisted_arguments( + fields_arg_value, valid_field_values_for_list_call + ) + bucket_name = module.params["name"] if bucket_name is not None: try: result = [ to_dict( object_storage_client.get_bucket( - module.params["namespace_name"], bucket_name + module.params["namespace_name"], bucket_name, **get_kwargs ).data ) ] except ServiceError as ex: module.fail_json(msg=ex.message) else: - result = list_buckets(object_storage_client, module) + result = list_buckets(object_storage_client, module, get_kwargs, list_kwargs) module.exit_json(buckets=result) diff --git a/library/oci_identity_provider.py b/library/oci_identity_provider.py new file mode 100644 index 0000000..3230dc1 --- /dev/null +++ b/library/oci_identity_provider.py @@ -0,0 +1,257 @@ +#!/usr/bin/python +# Copyright (c) 2017, 2018, 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_identity_provider +short_description: Manage Identity Providers in OCI +description: + - This module allows the user to create, delete and update identity providers in OCI. +version_added: "2.5" +options: + compartment_id: + description: The OCID of your tenancy. + type: str + description: + description: The description you assign to the IdentityProvider during creation. Does not have to be unique, + and it's changeable. + type: str + freeform_attributes: + description: Extra name value pairs associated with this identity provider. + type: dict + metadata: + description: The XML that contains the information required for federating. + type: str + metadata_url: + description: The URL for retrieving the identity provider's metadata, which contains information required + for federating. + type: str + name: + description: The name you assign to the IdentityProvider during creation. The name must be unique across all + IdentityProvider objects in the tenancy and cannot be changed. + type: str + product_type: + description: The identity provider service or product. Supported identity providers are Oracle Identity Cloud + Service (IDCS) and Microsoft Active Directory Federation Services (ADFS). + type: str + choices: + - IDCS + - ADFS + protocol: + description: The protocol used for federation. + type: str + choices: + - SAML2 + default: SAML2 + state: + description: Create or update an identity provider with I(state=present). Use I(state=absent) to delete + an identity provider. + type: str + default: present + choices: ['present', 'absent'] + identity_provider_id: + description: The OCID of the identity provider. Required when deleting the identity provider with + I(state=absent) or updating the identity provider with I(state=present). This option is mutually + exclusive with I(compartment_id). + type: str + aliases: [ 'id' ] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_creatable_resource, oracle_wait_options, oracle_tags ] +""" + +EXAMPLES = """ +- name: Create an identity provider + oci_identity_provider: + compartment_id: 'ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx' + description: test identity provider + freeform_attributes: + clientId: app_sf3kdjf3 + metadata_url: https://myidpserver/FederationMetadata/2007-06/FederationMetadata.xml + name: mytestidentityprovider + product_type: ADFS + protocol: SAML2 + +- name: Update description of an identity provider + oci_identity_provider: + identity_provider_id: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx + description: updated description + +- name: Delete the specified identity provider + oci_identity_provider: + identity_provider_id: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx + state: absent +""" + +RETURN = """ +identity_provider: + description: Information about the identity provider + returned: On successful create and update operation + type: dict + sample: { + "cidr_block": "10.0.0.0/16", + compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "default_dhcp_options_id": "ocid1.dhcpoptions.oc1.phx.xxxxxEXAMPLExxxxx", + "default_route_table_id": "ocid1.routetable.oc1.phx.xxxxxEXAMPLExxxxx", + "default_security_list_id": "ocid1.securitylist.oc1.phx.xxxxxEXAMPLExxxxx", + "display_name": "ansible_vcn", + "dns_label": "ansiblevcn", + "id": "ocid1.vcn.oc1.phx.xxxxxEXAMPLExxxxx", + "lifecycle_state": "AVAILABLE", + "time_created": "2017-11-13T20:22:40.626000+00:00", + "vcn_domain_name": "ansiblevcn.oraclevcn.com" + } +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + +try: + from oci.identity.identity_client import IdentityClient + from oci.identity.models import ( + CreateSaml2IdentityProviderDetails, + UpdateSaml2IdentityProviderDetails, + ) + + HAS_OCI_PY_SDK = True +except ImportError: + HAS_OCI_PY_SDK = False + +RESOURCE_TYPE = "identity_provider" + + +def delete_identity_provider(identity_client, module): + result = oci_utils.delete_and_wait( + resource_type=RESOURCE_TYPE, + client=identity_client, + get_fn=identity_client.get_identity_provider, + kwargs_get={"identity_provider_id": module.params["identity_provider_id"]}, + delete_fn=identity_client.delete_identity_provider, + kwargs_delete={"identity_provider_id": module.params["identity_provider_id"]}, + module=module, + ) + return result + + +def update_identity_provider(identity_client, module): + result = oci_utils.check_and_update_resource( + resource_type=RESOURCE_TYPE, + client=identity_client, + get_fn=identity_client.get_identity_provider, + kwargs_get={"identity_provider_id": module.params["identity_provider_id"]}, + update_fn=identity_client.update_identity_provider, + primitive_params_update=["identity_provider_id"], + kwargs_non_primitive_update={ + UpdateSaml2IdentityProviderDetails: "update_identity_provider_details" + }, + module=module, + update_attributes=UpdateSaml2IdentityProviderDetails().attribute_map.keys(), + ) + return result + + +def create_identity_provider(identity_client, module): + create_identity_provider_details = CreateSaml2IdentityProviderDetails() + for attribute in create_identity_provider_details.attribute_map.keys(): + if attribute in module.params: + setattr( + create_identity_provider_details, attribute, module.params[attribute] + ) + + result = oci_utils.create_and_wait( + resource_type=RESOURCE_TYPE, + create_fn=identity_client.create_identity_provider, + kwargs_create={ + "create_identity_provider_details": create_identity_provider_details + }, + client=identity_client, + get_fn=identity_client.get_identity_provider, + get_param="identity_provider_id", + module=module, + ) + return result + + +def main(): + module_args = oci_utils.get_taggable_arg_spec( + supports_create=True, supports_wait=True + ) + module_args.update( + dict( + compartment_id=dict(type="str"), + description=dict(type="str"), + freeform_attributes=dict(type="dict"), + metadata=dict(type="str"), + metadata_url=dict(type="str"), + name=dict(type="str"), + product_type=dict(type="str", choices=["IDCS", "ADFS"]), + protocol=dict(type="str", choices=["SAML2"], default="SAML2"), + state=dict(type="str", default="present", choices=["absent", "present"]), + identity_provider_id=dict(type="str", aliases=["id"]), + ) + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[["compartment_id", "identity_provider_id"]], + ) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + identity_client = oci_utils.create_service_client(module, IdentityClient) + + exclude_attributes = {} + state = module.params["state"] + identity_provider_id = module.params.get("identity_provider_id") + + if state == "absent": + if identity_provider_id: + result = delete_identity_provider(identity_client, module) + else: + module.fail_json( + msg="Specify identity_provider_id with state as 'absent' to delete the identity provider." + ) + + else: + if identity_provider_id: + result = update_identity_provider(identity_client, module) + elif module.params.get("compartment_id"): + result = oci_utils.check_and_create_resource( + resource_type="identity_provider", + create_fn=create_identity_provider, + kwargs_create={"identity_client": identity_client, "module": module}, + list_fn=identity_client.list_identity_providers, + kwargs_list={ + "protocol": module.params.get("protocol"), + "compartment_id": module.params["compartment_id"], + }, + module=module, + model=CreateSaml2IdentityProviderDetails(), + exclude_attributes=exclude_attributes, + ) + else: + module.fail_json( + msg="Either provide identity_provider_id to update an existing identity provider or " + "compartment_id to create a new identity provider." + ) + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_identity_provider_facts.py b/library/oci_identity_provider_facts.py new file mode 100644 index 0000000..0041a8c --- /dev/null +++ b/library/oci_identity_provider_facts.py @@ -0,0 +1,241 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_identity_provider_facts +short_description: Retrieve details about published App Catalog listings in OCI Compute Service +description: + - This module retrieves information of a specified app catalog listing or lists all the app catalog listings + in the tenancy. +version_added: "2.5" +options: + identity_provider_id: + description: The OCID of the identity provider. Required to get information of a specific identity provider. + type: str + aliases: ["id"] + protocol: + description: The protocol used for federation. + type: str + choices: ["SAML2"] + default: "SAML2" + compartment_id: + description: The OCID of the tenancy (remember that the tenancy is simply the root compartment). + type: str + name: + description: Filter the identity providers with given name. + type: str +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle ] +""" + +EXAMPLES = """ +- name: Get all identity providers of given protocol in the tenancy + oci_identity_provider_facts: + protocol: SAML2 + compartment_id: ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx + +- name: Get a specific identity provider using its OCID + oci_identity_provider_facts: + identity_provider_id: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx +""" + +RETURN = """ +identity_providers: + description: List of identity provider details + returned: on success + type: complex + contains: + compartment_id: + description: The OCID of the tenancy containing the IdentityProvider. + returned: success + type: str + sample: ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx + defined_tags: + description: Defined tags for this resource. Each key is predefined and scoped to a namespace. + returned: success + type: str + sample: {"Operations": {"CostCenter": "42"}} + description: + description: The description you assign to the IdentityProvider during creation. + returned: success + type: str + sample: Test identity provider + freeform_tags: + description: Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, + type, or namespace. + returned: success + type: str + sample: {"Department": "Finance"} + id: + description: The OCID of the IdentityProvider. + returned: success + type: str + sample: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx + inactive_status: + description: The detailed status of INACTIVE lifecycleState. + returned: success + type: str + sample: null + lifecycle_state: + description: The current state. After creating an IdentityProvider, make sure its lifecycleState changes + from CREATING to ACTIVE before using it. + returned: success + type: str + sample: ACTIVE + metadata_url: + description: The URL for retrieving the identity provider's metadata, which contains information required + for federating. + returned: success + type: str + sample: https://idcs-31ddf5c2bxxxxxxx429d5c2c927.identity.oraclecloud.com + name: + description: The name you assign to the IdentityProvider during creation. The name must be unique across + all IdentityProvider objects in the tenancy and cannot be changed. This is the name federated + users see when choosing which identity provider to use when signing in to the + Oracle Cloud Infrastructure Console. + returned: success + type: str + sample: TEST_IDENTITY_PROVDER + product_type: + description: The identity provider service or product. Supported identity providers are Oracle Identity + Cloud Service (IDCS) and Microsoft Active Directory Federation Services (ADFS). + returned: success + type: str + sample: ADFS + protocol: + description: The protocol used for federation. + returned: success + type: str + sample: SAML2 + redirect_url: + description: The URL to redirect federated users to for authentication with the identity provider. + returned: success + type: str + sample: https://idpinstance.ansibletest.com/adfs/ls/ + signing_certificate: + description: The identity provider's signing certificate used by the IAM Service to validate the SAML2 + token. + returned: success + type: str + sample: null + time_created: + description: Date and time the IdentityProvider was created, in the format defined by RFC3339. + returned: success + type: str + sample: 2016-08-25T21:10:29.600Z + sample: [{ + "compartment_id": "ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx", + "defined_tags": {}, + "description": "Test Identity Provider", + "freeform_attributes": {}, + "freeform_tags": {}, + "id": "ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx", + "inactive_status": null, + "lifecycle_state": "ACTIVE", + "metadata_url": null, + "name": "TEST_IDENTITY_PROVDER", + "product_type": "ADFS", + "protocol": "SAML2", + "redirect_url": "https://testidp.oracletest.com/adfs/ls/", + "signing_certificate": null, + "time_created": "2019-04-01T21:49:41.934000+00:00" + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + +try: + from oci.identity.identity_client import IdentityClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_identity_providers(identity_client, module): + optional_list_method_params = ["name"] + optional_kwargs = dict( + (param, module.params[param]) + for param in optional_list_method_params + if module.params.get(param) is not None + ) + return to_dict( + oci_utils.list_all_resources( + identity_client.list_identity_providers, + protocol=module.params.get("protocol"), + compartment_id=module.params.get("compartment_id"), + **optional_kwargs + ) + ) + + +def get_identity_provider(identity_client, module): + return to_dict( + [ + oci_utils.call_with_backoff( + identity_client.get_identity_provider, + identity_provider_id=module.params.get("identity_provider_id"), + ).data + ] + ) + + +def main(): + module_args = oci_utils.get_facts_module_arg_spec(filter_by_name=True) + module_args.update( + dict( + identity_provider_id=dict(type="str", aliases=["id"]), + protocol=dict(type="str", choices=["SAML2"], default="SAML2"), + compartment_id=dict(type="str"), + ) + ) + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[ + ["identity_provider_id", "compartment_id"], + ["identity_provider_id", "protocol"], + ], + ) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + identity_client = oci_utils.create_service_client(module, IdentityClient) + + try: + if module.params.get("identity_provider_id"): + result = get_identity_provider(identity_client, module) + elif module.params.get("compartment_id"): + result = list_identity_providers(identity_client, module) + else: + module.fail_json( + msg="Specify compartment_id and protocol to get all the identity providers of the given protocol " + "in the compartment or identity_provider_id to retrieve a specific identity provider." + ) + except ServiceError as se: + module.fail_json(msg=se.message) + + module.exit_json(identity_providers=result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_idp_group_mapping.py b/library/oci_idp_group_mapping.py new file mode 100644 index 0000000..37a71ee --- /dev/null +++ b/library/oci_idp_group_mapping.py @@ -0,0 +1,297 @@ +#!/usr/bin/python +# Copyright (c) 2017, 2018, 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_idp_group_mapping +short_description: Create, update and delete Identity Provider (IdP) group mappings. +description: Create, update and delete IdP group mappings. +version_added: "2.5" +options: + identity_provider_id: + description: The identifier of the identity provider the IdP group mapping belongs to. + required: true + type: str + mapping_id: + description: The identifier of the IdpGroupMapping to update or delete. + aliases: ['id'] + type: str + idp_group_name: + description: The IdP group name. + type: str + group_id: + description: The identifier of the IAM Service group that is mapped to the IdP group. + type: str + state: + description: Create, update or delete an IdP group mapping. For I(state=present), if the mapping does not exist, + it gets created. If it does exist, it gets updated. For I(state=absent), the mapping gets deleted. + required: false + default: 'present' + choices: ['present','absent'] + +author: "Mike Ross (@mikeross)" +extends_documentation_fragment: oracle +""" + +EXAMPLES = """ +- name: Create IdP group mapping + oci_idp_group_mapping: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + group_id: 'ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda' + idp_group_name: IdPGroupName + +- name: Update IdP group name of an IdP group mapping + oci_idp_group_mapping: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + mapping_id: 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba' + idp_group_name: IdPGroupName + group_id: 'ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda' + +- name: Deletes an IdP group mapping + oci_idp_group_mapping: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + mapping_id: 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba' + state: "absent" +""" + +RETURN = """ +idp_group_mapping: + description: Attributes of the created / updated IdP group mapping + returned: on success + type: complex + contains: + id: + description: The identifier of the IdpGroupMapping. + returned: always + type: string + sample: ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba + idp_id: + description: The identifier of the Identity Provider this mapping belongs to. + returned: always + type: string + sample: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq + idp_group_name: + description: The name of the IdP group that is mapped to the IAM Service group. + returned: always + type: string + sample: IdPGroupName + group_id: + description: The identifier of the IAM Service group that is mapped to the IdP group. + returned: always + type: string + sample: ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda + compartment_id: + description: The identifier of the tenancy containing the Identity Provider. + returned: always + type: string + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq + time_created: + description: Date and time the mapping was created. + returned: always + type: datetime + sample: 2016-08-25T21:10:29.600Z + lifecycle_state: + description: The mapping's current state. After creating a mapping object, make sure its lifecycle_state changes + from CREATING to ACTIVE before using it. + returned: always + type: string + sample: ACTIVE + inactive_status: + description: The detailed status of INACTIVE lifecycle_state. + returned: always + type: int + sample: 0 + sample: { + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq", + "group_id": "ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda", + "id": "ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba", + "idp_group_name": "IdPGroupName", + "idp_id": "ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq", + "inactive_status": null, + "lifecycle_state": "ACTIVE", + "time_created": "2016-08-25T21:10:29.600Z" + } +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + +try: + from oci.identity.identity_client import IdentityClient + from oci.exceptions import ServiceError, ClientError + from oci.identity.models import ( + CreateIdpGroupMappingDetails, + UpdateIdpGroupMappingDetails, + ) + + HAS_OCI_PY_SDK = True +except ImportError: + HAS_OCI_PY_SDK = False + + +def create_idp_group_mapping(identity_client, module): + create_idp_group_mapping_details = CreateIdpGroupMappingDetails() + for attribute in create_idp_group_mapping_details.attribute_map: + create_idp_group_mapping_details.__setattr__( + attribute, module.params.get(attribute) + ) + + identity_provider_id = module.params.get("identity_provider_id") + + result = oci_utils.create_and_wait( + resource_type="idp_group_mapping", + create_fn=identity_client.create_idp_group_mapping, + kwargs_create={ + "identity_provider_id": identity_provider_id, + "create_idp_group_mapping_details": create_idp_group_mapping_details, + }, + client=identity_client, + get_fn=identity_client.get_idp_group_mapping, + get_param="mapping_id", + kwargs_get={"identity_provider_id": identity_provider_id}, + module=module, + ) + + return result + + +def update_idp_group_mapping(identity_client, module): + identity_provider_id = module.params.get("identity_provider_id") + idp_group_mapping_id = module.params.get("mapping_id") + + return oci_utils.check_and_update_resource( + resource_type="idp_group_mapping", + client=identity_client, + get_fn=identity_client.get_idp_group_mapping, + kwargs_get={ + "identity_provider_id": identity_provider_id, + "mapping_id": idp_group_mapping_id, + }, + update_fn=identity_client.update_idp_group_mapping, + primitive_params_update=["mapping_id", "identity_provider_id"], + kwargs_non_primitive_update={ + UpdateIdpGroupMappingDetails: "update_idp_group_mapping_details" + }, + module=module, + update_attributes=UpdateIdpGroupMappingDetails().attribute_map.keys(), + required_update_attributes=["group_id", "idp_group_name"], + ) + + +def delete_idp_group_mapping(identity_client, module): + result = oci_utils.delete_and_wait( + resource_type="idp_group_mapping", + client=identity_client, + get_fn=identity_client.get_idp_group_mapping, + kwargs_get={ + "mapping_id": module.params["mapping_id"], + "identity_provider_id": module.params["identity_provider_id"], + }, + delete_fn=identity_client.delete_idp_group_mapping, + kwargs_delete={ + "mapping_id": module.params["mapping_id"], + "identity_provider_id": module.params["identity_provider_id"], + }, + module=module, + ) + + return result + + +def set_logger(input_logger): + global logger + logger = input_logger + + +def get_logger(): + return logger + + +def main(): + logger = oci_utils.get_logger("oci_idp_group_mapping") + set_logger(logger) + + module_args = oci_utils.get_common_arg_spec() + module_args.update( + dict( + mapping_id=dict(type="str", required=False, aliases=["id"]), + identity_provider_id=dict(type="str", required=True), + idp_group_name=dict(type="str", required=False), + group_id=dict(type="str", required=False), + state=dict( + type="str", + required=False, + default="present", + choices=["present", "absent"], + ), + ) + ) + + module = AnsibleModule(argument_spec=module_args, supports_check_mode=False) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + identity_client = oci_utils.create_service_client(module, IdentityClient) + state = module.params["state"] + idp_group_mapping_id = module.params.get("mapping_id") + + if state == "present": + try: + if idp_group_mapping_id: + operation_display_text = "update" + result = update_idp_group_mapping(identity_client, module) + else: + operation_display_text = "create" + result = oci_utils.check_and_create_resource( + resource_type="idp_group_mapping", + create_fn=create_idp_group_mapping, + kwargs_create={ + "identity_client": identity_client, + "module": module, + }, + list_fn=identity_client.list_idp_group_mappings, + kwargs_list={ + "identity_provider_id": module.params.get( + "identity_provider_id" + ) + }, + module=module, + model=CreateIdpGroupMappingDetails(), + ) + except ServiceError as ex: + get_logger().error( + "Unable to %s IdpGroupMapping due to: %s", + operation_display_text, + ex.message, + ) + module.fail_json(msg=ex.message) + except ClientError as ex: + get_logger().error( + "Unable to %s IdpGroupMapping due to: %s", + operation_display_text, + str(ex), + ) + module.fail_json(msg=str(ex)) + elif state == "absent": + result = delete_idp_group_mapping(identity_client, module) + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_idp_group_mapping_facts.py b/library/oci_idp_group_mapping_facts.py new file mode 100644 index 0000000..7c30372 --- /dev/null +++ b/library/oci_idp_group_mapping_facts.py @@ -0,0 +1,165 @@ +#!/usr/bin/python +# Copyright (c) 2017, 2018, 2019 Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_idp_group_mapping_facts +short_description: Retrieve details of all Identity Provider (IdP) group mappings for a given Identity Provider. +description: + - This module retrieves details of all Identity Provider (IdP) group mappings for a given Identity Provier. +version_added: "2.5" +options: + identity_provider_id: + description: The identifier of the identity provider to fetch group mappings for. + required: true + type: str + mapping_id: + description: The identifier of the group mapping to fetch the details of. + aliases: ['id'] + type: str + +author: "Mike Ross (@mikeross)" +extends_documentation_fragment: oracle +""" + +EXAMPLES = """ +- name: Get details of all IdP group mappings for a given identity provider + oci_idp_group_mapping_facts: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + +- name: Get the details of a single IdP group mapping + oci_idp_group_mapping_facts: + identity_provider_id: 'ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq' + mapping_id: 'ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba' +""" + +RETURN = """ +idp_group_mappings: + description: Information about one or more IdP group mappings + returned: on success + type: complex + contains: + id: + description: The identifier of the IdpGroupMapping. + returned: always + type: string + sample: ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba + idp_id: + description: The identifier of the Identity Provider this mapping belongs to. + returned: always + type: string + sample: ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq + idp_group_name: + description: The name of the IdP group that is mapped to the IAM Service group. + returned: always + type: string + sample: IdPGroupName + group_id: + description: The identifier of the IAM Service group that is mapped to the IdP group. + returned: always + type: string + sample: ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda + compartment_id: + description: The identifier of the tenancy containing the Identity Provider. + returned: always + type: string + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq + time_created: + description: Date and time the mapping was created. + returned: always + type: datetime + sample: 2016-08-25T21:10:29.600Z + lifecycle_state: + description: The mapping's current state. After creating a mapping object, make sure its lifecycle_state changes + from CREATING to ACTIVE before using it. + returned: always + type: string + sample: ACTIVE + inactive_status: + description: The detailed status of INACTIVE lifecycle_state. + returned: always + type: int + sample: 0 + sample: [{ + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx..6glmkwq", + "group_id": "ocid1.group.oc1..xxxxxEXAMPLExxxxxsdxbsfda", + "id": "ocid1.idpgroupmapping.oc1..xxxxxEXAMPLExxxxxbnmfuwba", + "idp_group_name": "IdPGroupName", + "idp_id": "ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxxbn4q4eq", + "inactive_status": null, + "lifecycle_state": "ACTIVE", + "time_created": "2016-08-25T21:10:29.600Z" + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + +try: + from oci.identity.identity_client import IdentityClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_idp_group_mappings(identity_client, module): + try: + idp_id = module.params["identity_provider_id"] + idp_group_mapping_id = module.params["mapping_id"] + + if idp_group_mapping_id: + idp_group_mappings = [ + oci_utils.call_with_backoff( + identity_client.get_idp_group_mapping, + identity_provider_id=idp_id, + mapping_id=idp_group_mapping_id, + ).data + ] + else: + idp_group_mappings = oci_utils.list_all_resources( + identity_client.list_idp_group_mappings, identity_provider_id=idp_id + ) + except ServiceError as ex: + module.fail_json(msg=ex.message) + return to_dict(idp_group_mappings) + + +def main(): + module_args = oci_utils.get_common_arg_spec() + module_args.update( + dict( + identity_provider_id=dict(type="str", required=True, aliases=["id"]), + mapping_id=dict(type="str", required=False), + ) + ) + + module = AnsibleModule(argument_spec=module_args, supports_check_mode=False) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + identity_client = oci_utils.create_service_client(module, IdentityClient) + + result = list_idp_group_mappings(identity_client, module) + module.exit_json(idp_group_mappings=result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_instance.py b/library/oci_instance.py index 223995b..b1f7adf 100644 --- a/library/oci_instance.py +++ b/library/oci_instance.py @@ -31,17 +31,14 @@ availability_domain: description: The Availability Domain of the instance. Required when creating a compute instance with I(state=present). - required: false boot_volume_details: description: Details for attaching/detaching a boot volume to/from an instance. I(boot_volume_details) is mutually exclusive with I(image_id). This option is only supported in experimental mode. To use an experimental feature, set the environment variable OCI_ANSIBLE_EXPERIMENTAL to True. - required: false suboptions: attachment_state: description: Attach a boot volume to the instance I(instance_id) with I(attachment_state=present). Detach a boot volume from the instance I(instance_id) with I(attachment_state=absent). - required: false default: present choices: ['present', 'absent'] boot_volume_id: @@ -49,7 +46,6 @@ required: true compartment_id: description: The OCID of the compartment. Required when I(state=present). - required: false extended_metadata: description: Additional metadata key/value pairs that you provide. They serve a similar purpose and functionality from fields in the I(metadata) object. They are distinguished from I(metadata) @@ -57,7 +53,6 @@ only). If you don't need nested metadata values, it is strongly advised to avoid using this object and use the Metadata object instead. - required: false exact_count: description: Indicates how many instances that match the I(count_tag) option should be running. This must be used with I(state=present) and a valid I(count_tag). If the number of compute instances that match @@ -72,13 +67,13 @@ assigned as the display_name of a newly provisioned instance. For example, if I(display_name) is 'my_web_server', new compute instances would be called 'my_web_server_0', 'my_web_server_1' and so on. To control the generated display name in a fine-grained manner, use "printf" style - format in I(display_name) such as 'my_%d_web_server'. - required: false + format in I(display_name) such as 'my_%d_web_server'. This option is deprecated and will be removed + in a future release. Please use M(oci_instance_pool) instead to create multiple compute instances. count_tag: description: Used with I(exact_count) to determine how many compute instances matching the specific tag criteria C(count_tag) must be running. Only I(defined_tags) associated with an instance are considered for - matching against C(count_tag). - required: false + matching against C(count_tag). This option is deprecated and will be removed in a future release. + Please use M(oci_instance_pool) instead to create multiple compute instances. fault_domain: description: A fault domain is a grouping of hardware and infrastructure within an availability domain. Each availability domain contains three fault domains. Fault domains let you distribute your instances @@ -87,53 +82,46 @@ other fault domains. If you do not specify the fault domain, the system selects one for you. To change the fault domain for an instance, terminate it and launch a new instance in the preferred fault domain. To get a list of fault domains, use M(oci_fault_domain_facts). - required: false metadata: description: A hash/dictionary of custom key/value pairs that are associated with the instance. This option is also used to provide information to cloud-init and specifying "ssh_authorized_keys" for the default user of the instance. This hash is specified as '{"key":"value"}' and '{"key":"value","key":"value"}'. - required: false display_name: description: A user-friendly name. Does not have to be unique, and it's changeable. Avoid entering confidential information. If a C(display_name) is specified, and if I(exact_count) is specified, the display name would be suffixed with an auto-incrementing integer. - required: false aliases: ['name'] image_id: description: The OCID of the image used to boot the instance. I(image_id) is mutually exclusive with I(boot_volume_details) and I(source_details). This option is deprecated. Use I(source_details) with I(source_type=image) instead. - required: false instance_id: description: The OCID of the compute instance. Required for updating an existing compute instance when I(state=present), for performing power actions (such as start, stop, softreset or reset) on an instance, and for terminating an instance I(state=absent). - required: false aliases: [ 'id' ] ipxe_script: description: custom iPXE script that will run when the instance boots. - required: false preserve_boot_volume: description: Whether to preserve the boot volume when terminating an instance with I(state=absent). - required: false default: False type: bool enable_parallel_requests: description: Whether to scale up and down I(exact_count) instances in parallel. By default, I(exact_count) - instances are launched or terminated in parallel. - required: False + instances are launched or terminated in parallel. This option is deprecated and will be removed in + a future release. Please use M(oci_instance_pool) instead to create multiple compute instances. default: True type: bool max_thread_count: description: When I(enable_parallel_requests=True), indicates the number of maximum parallel operations that are used to launch or terminate I(exact_count) instances. The default number of threads used is the - number of cores in your machine. - required: False + number of cores in your machine. This option is deprecated and will be removed in a future release. + Please use M(oci_instance_pool) instead + to create multiple compute instances. type: int shape: description: The shape of the instance. Required when creating a compute instance with I(state=present). - required: false source_details: description: Details for creating an instance. Use this parameter to specify whether a boot volume or an image should be used to launch a new instance. @@ -146,14 +134,12 @@ choices: ['image', 'bootVolume'] image_id: description: The OCID of the image used to boot the instance. Required if I(source_type) is "image". - required: false boot_volume_size_in_gbs: description: The size of the boot volume in GBs. Minimum value is 50 GB and maximum value is 16384 GB (16TB). Applicable only when I(source_type=image). boot_volume_id: description: The OCID of the boot volume used to boot the instance. Required if I(source_type) is "bootVolume". - required: false state: description: The state of the instance that must be asserted to. When I(state=present), and the compute instance doesn't exist, the instance is launched/created with the specified @@ -165,37 +151,30 @@ Note that I(state=softreset) and I(state=reset) states are not idempotent. Every time a play is executed with these C(state) options, a shutdown and a power on sequence is executed against the instance. - required: false default: "present" choices: ['present', 'absent', 'running', 'reset', 'softreset', 'stopped'] volume_details: description: Details for attaching or detaching a volume to an instance with I(state=present) or I(state=RUNNING). This option is only supported in experimental mode. To use an experimental feature, set the environment variable OCI_ANSIBLE_EXPERIMENTAL to True. - required: false suboptions: attachment_state: description: Attach a volume to the instance I(instance_id) with I(attachment_state=present). Detach a volume from the instance I(instance_id) with I(attachment_state=absent). - required: false default: present choices: ['present', 'absent'] attachment_name: description: A user-friendly name. Does not have to be unique, and it cannot be changed. Avoid entering confidential information. - required: false type: description: The type of volume. The only supported value is "iscsi". - required: false default: iscsi choices: ['iscsi'] volume_id: description: The OCID of the volume to be attached to or detached from the instance I(instance_id). - required: false vnic: description: Details for the primary VNIC that is automatically created and attached when the instance is launched. Required when creating a compute instance with I(state=present). - required: false aliases: ['create_vnic_details'] suboptions: assign_public_ip: @@ -206,27 +185,22 @@ I(prohibitPublicIpOnVnic = false), then a public IP address is assigned. If set to true and I(prohibitPublicIpOnVnic = true), an error is returned. - required: false hostname_label: description: The hostname for the VNIC's primary private IP. Used for DNS. The value is the hostname portion of the primary private IP's fully qualified domain name (FQDN) (for example, bminstance-1 in FQDN bminstance-1.subnet123.vcn1.oraclevcn.com). Must be unique across all VNICs in the subnet and comply with RFC 952 and RFC 1123. - required: false name: description: A user-friendly name for the VNIC. Does not have to be unique. - required: false private_ip: description: The private IP to assign to the VNIC. Must be an available IP address within the subnet's CIDR. If you don't specify a value, Oracle automatically assigns a private IP address from the subnet. This is the VNIC's primary private IP address. - required: false skip_source_dest_check: description: Determines whether the source/destination check is disabled on the VNIC. Defaults to false, which means the check is performed. - required: false default: false subnet_id: description: The OCID of the subnet to create the VNIC in. @@ -1197,6 +1171,7 @@ try: import oci from oci.core.compute_client import ComputeClient + from oci.core.virtual_network_client import VirtualNetworkClient from oci.core.models import AttachBootVolumeDetails from oci.core.models import AttachVolumeDetails from oci.core.models import LaunchInstanceDetails @@ -1676,6 +1651,21 @@ def attach_boot_volume(compute_client, module, attach_boot_volume_details): ) +def add_primary_ip_info(module, compute_client, network_client, result): + if "instances" in result: + for instance in result["instances"]: + try: + primary_public_ip, primary_private_ip = oci_compute_utils.get_primary_ips( + compute_client, network_client, instance + ) + instance["primary_public_ip"] = primary_public_ip + instance["primary_private_ip"] = primary_private_ip + except ServiceError as ex: + instance["primary_public_ip"] = None + instance["primary_private_ip"] = None + module.fail_json(msg=ex.message) + + def get_attach_boot_volume_details(instance_id, boot_volume_id, attachment_name=None): attach_boot_volume_details = AttachBootVolumeDetails() attach_boot_volume_details.display_name = attachment_name @@ -2161,18 +2151,22 @@ def main(): availability_domain=dict(type="str", required=False), boot_volume_details=dict(type="dict", required=False), compartment_id=dict(type="str", required=False), - count_tag=dict(type="dict", required=False), - exact_count=dict(type="int", required=False), + count_tag=dict(type="dict", required=False, removed_in_version="v1.10.0"), + exact_count=dict(type="int", required=False, removed_in_version="v1.10.0"), extended_metadata=dict(type="dict", required=False), fault_domain=dict(type="str", required=False), instance_id=dict(type="str", required=False, aliases=["id"]), image_id=dict(type="str", required=False), ipxe_script=dict(type="str", required=False), - max_thread_count=dict(type="int", required=False), + max_thread_count=dict( + type="int", required=False, removed_in_version="v1.10.0" + ), metadata=dict(type="dict", required=False), name=dict(type="str", required=False, aliases=["display_name"]), preserve_boot_volume=dict(type="bool", required=False, default=False), - enable_parallel_requests=dict(type="bool", required=False, default=True), + enable_parallel_requests=dict( + type="bool", required=False, default=True, removed_in_version="v1.10.0" + ), shape=dict(type="str", required=False), state=dict( type="str", @@ -2211,6 +2205,7 @@ def main(): module.fail_json(msg="oci python sdk required for this module.") compute_client = oci_utils.create_service_client(module, ComputeClient) + network_client = oci_utils.create_service_client(module, VirtualNetworkClient) state = module.params["state"] result = dict(changed=False) @@ -2300,6 +2295,7 @@ def main(): ) add_volume_attachment_info(module, compute_client, result) add_boot_volume_attachment_info(module, compute_client, result) + add_primary_ip_info(module, compute_client, network_client, result) module.exit_json(**result) except ServiceError as se: module.fail_json(msg=se.message) diff --git a/library/oci_instance_configuration.py b/library/oci_instance_configuration.py index 616710f..e382e9b 100644 --- a/library/oci_instance_configuration.py +++ b/library/oci_instance_configuration.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -285,7 +285,7 @@ """ EXAMPLES = """ -- name: Create an instance configuration that describes launch details for a compute instance of VM.Standard1.1 shape +- name: Create an instance configuration that describes launch details for a compute instance of VM.Standard2.1 shape and a specific image. No details are provided for additional block volume attachments or secondary VNICs oci_instance_configuration: name: "backend-servers" @@ -294,14 +294,14 @@ instance_type: "compute" launch_details: compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...vm62xq" - shape: "VM.Standard1.1" + shape: "VM.Standard2.1" source_details: source_type: "image" image_id: "ocid1.image.oc1.phx.xxxxxEXAMPLExxxxx...sa7klnoa" metadata: foo: bar -- name: Create an instance configuration that describes launch details for a compute instance of VM.Standard1.1 shape +- name: Create an instance configuration that describes launch details for a compute instance of VM.Standard2.1 shape and a specific image, with additional block volume details (stating that a new block volume must be created and that it must be a clone of an existing volume, and an existing iscsi volume be attached) oci_instance_configuration: @@ -311,7 +311,7 @@ instance_type: "compute" launch_details: compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx...vm62xq" - shape: "VM.Standard1.1" + shape: "VM.Standard2.1" source_details: source_type: "image" image_id: "ocid1.image.oc1.phx.xxxxxEXAMPLExxxxx...sa7klnoa" @@ -653,7 +653,7 @@ "ssh_authorized_keys": "ssh-rsa ...k8Id/ug/xxxxxEXAMPLExxxxx...RYzAEYT foo@bar", "user_data": "dW5kZWZpbmVk" }, - "shape": "VM.Standard1.1", + "shape": "VM.Standard2.1", "source-details": { "image-id": "ocid1.image.oc1.iad.xxxxxEXAMPLExxxxx...ayda", "source-type": "image" diff --git a/library/oci_instance_configuration_facts.py b/library/oci_instance_configuration_facts.py index 78da313..9d5df5d 100644 --- a/library/oci_instance_configuration_facts.py +++ b/library/oci_instance_configuration_facts.py @@ -376,7 +376,7 @@ "ssh_authorized_keys": "ssh-rsa ...k8Id/ug/xxxxxEXAMPLExxxxx...RYzAEYT foo@bar", "user_data": "dW5kZWZpbmVk" }, - "shape": "VM.Standard1.1", + "shape": "VM.Standard2.1", "source-details": { "image-id": "ocid1.image.oc1.iad.xxxxxEXAMPLExxxxx...ayda", "source-type": "image" diff --git a/library/oci_instance_facts.py b/library/oci_instance_facts.py index 643104f..54f6248 100644 --- a/library/oci_instance_facts.py +++ b/library/oci_instance_facts.py @@ -27,19 +27,18 @@ compartment_id: description: The OCID of the compartment (either the tenancy or another compartment in the tenancy). Required for retrieving information about all instances in a Compartment/Tenancy. - required: false + type: str availability_domain: description: The name of the Availability Domain. - required: false + type: str instance_id: description: The OCID of the instance. Required for retrieving information about a specific instance. - required: false + type: str aliases: ['id'] lifecycle_state: description: A filter to only return resources that match the given lifecycle state. The state value is - case-insensitive. Allowed values are "PROVISIONING", "RUNNING", "STARTING", "STOPPING", - "STOPPED", "CREATING_IMAGE", "TERMINATING", "TERMINATED" - required: false + case-insensitive. + type: str choices: ["PROVISIONING", "RUNNING", "STARTING", "STOPPING", "STOPPED", "CREATING_IMAGE", "TERMINATING", "TERMINATED"] @@ -319,7 +318,7 @@ HAS_OCI_PY_SDK = False -def list_instances(compute_client, network_client, module): +def list_instances(compute_client, module): try: cid = module.params["compartment_id"] optional_list_method_params = [ @@ -359,33 +358,16 @@ def add_volume_attachment_facts(compute_client, result): def add_primary_ips(compute_client, network_client, result, module): for instance in result: - instance["primary_public_ip"] = None - instance["primary_private_ip"] = None - - vnic_attachments = oci_utils.list_all_resources( - compute_client.list_vnic_attachments, - compartment_id=instance["compartment_id"], - instance_id=instance["id"], - ) - - if vnic_attachments: - for vnic_attachment in vnic_attachments: - if vnic_attachment.lifecycle_state == "ATTACHED": - try: - vnic = network_client.get_vnic(vnic_attachment.vnic_id).data - if vnic.is_primary: - if vnic.public_ip: - instance["primary_public_ip"] = vnic.public_ip - if vnic.private_ip: - instance["primary_private_ip"] = vnic.private_ip - except ServiceError as ex: - if ex.status == 404: - get_logger().debug( - "Either VNIC with ID %s does not exist or you are not authorized to access it.", - vnic_attachment.vnic_id, - ) - else: - module.fail_json(msg=ex.message) + try: + primary_public_ip, primary_private_ip = oci_compute_utils.get_primary_ips( + compute_client, network_client, instance + ) + instance["primary_public_ip"] = primary_public_ip + instance["primary_private_ip"] = primary_private_ip + except ServiceError as ex: + instance["primary_public_ip"] = None + instance["primary_private_ip"] = None + module.fail_json(msg=ex.message) def set_logger(input_logger): @@ -442,7 +424,7 @@ def main(): result = dict(changed=False) if compartment_id: - result = list_instances(compute_client, network_client, module) + result = list_instances(compute_client, module) add_primary_ips(compute_client, network_client, result, module) else: try: diff --git a/library/oci_node_pool.py b/library/oci_node_pool.py index 67a6ff4..3cd763b 100644 --- a/library/oci_node_pool.py +++ b/library/oci_node_pool.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019 Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -104,7 +104,7 @@ name: test_node_pool kubernetes_version: "v1.9.7" node_image_name: "Oracle-Linux-7.4" - node_shape: "VM.Standard1.1" + node_shape: "VM.Standard2.1" quantity_per_subnet: 1 subnet_ids: - "ocid1.subnet.oc1..xxxxxEXAMPLExxxxx...abcd" @@ -192,7 +192,7 @@ description: The name of the node shape of the nodes in the node pool. returned: always type: string - sample: VM.Standard1.1 + sample: VM.Standard2.1 nodes: description: The nodes in the node pool. returned: always @@ -228,7 +228,7 @@ "name": "test_node_pool", "node_image_id": "ocid1.image.oc1..xxxxxEXAMPLExxxxx", "node_image_name": "Oracle-Linux-7.4", - "node_shape": "VM.Standard1.1", + "node_shape": "VM.Standard2.1", "nodes": [ { "availability_domain": "IwGV:US-ASHBURN-AD-1", diff --git a/library/oci_node_pool_facts.py b/library/oci_node_pool_facts.py index 1e2851a..aa15d88 100644 --- a/library/oci_node_pool_facts.py +++ b/library/oci_node_pool_facts.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -112,7 +112,7 @@ description: The name of the node shape of the nodes in the node pool. returned: always type: string - sample: VM.Standard1.1 + sample: VM.Standard2.1 nodes: description: The nodes in the node pool. returned: when retrieving a specific node pool @@ -148,7 +148,7 @@ "name": "test_node_pool", "node_image_id": "ocid1.image.oc1..xxxxxEXAMPLExxxxx", "node_image_name": "Oracle-Linux-7.4", - "node_shape": "VM.Standard1.1", + "node_shape": "VM.Standard2.1", "nodes": [ { "availability_domain": "IwGV:US-ASHBURN-AD-1", diff --git a/library/oci_node_pool_options_facts.py b/library/oci_node_pool_options_facts.py index 718a0a1..e5ed26f 100644 --- a/library/oci_node_pool_options_facts.py +++ b/library/oci_node_pool_options_facts.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -74,9 +74,9 @@ "shapes": [ "VM.Standard2.1", "VM.Standard2.2", - "VM.Standard1.1", - "VM.Standard1.2", - "VM.DenseIO1.4" + "VM.Standard2.4", + "VM.Standard2.8", + "VM.DenseIO2.8" ] } """ diff --git a/library/oci_object.py b/library/oci_object.py index 8dab22b..27e1eaa 100644 --- a/library/oci_object.py +++ b/library/oci_object.py @@ -188,7 +188,7 @@ try: from oci.object_storage.object_storage_client import ObjectStorageClient from oci.exceptions import ServiceError - from oci.object_storage import UploadManager, MultipartObjectAssembler + from oci.object_storage import UploadManager HAS_OCI_PY_SDK = True except ImportError: @@ -236,6 +236,15 @@ def get_object(object_storage_client, module): except ServiceError as ex: module.fail_json(msg=ex.message) + # create dest file if it does not exist + try: + with open(dest, "a"): + pass + except IOError as ioex: + module.fail_json( + msg="Error opening/creating the dest file: {0}".format(str(ioex)) + ) + # Check if file exists with the same checksum. Get md5 hexdigest of the file content, convert it to binary and then # get base-64 encoded MD5 hash. dest_md5 = base64.b64encode(base64.b16decode(module.md5(dest), True)).decode( @@ -351,14 +360,31 @@ def put_object(object_storage_client, module): def abort_multipart_upload(object_storage_client, module): result = dict(changed=False) - multipart_object_assembler = MultipartObjectAssembler( - object_storage_client, - module.params.get("namespace_name"), - module.params.get("bucket_name"), - module.params.get("object_name"), + multipart_upload_exists = False + # oci sdk does not fail even if the upload id does not exist. So check and set changed to False if + # the upload id does not exist + multipart_uploads = oci_utils.list_all_resources( + object_storage_client.list_multipart_uploads, + namespace_name=module.params.get("namespace_name"), + bucket_name=module.params.get("bucket_name"), ) + for multipart_upload in multipart_uploads: + if multipart_upload.object == module.params.get( + "object_name" + ) and multipart_upload.upload_id == module.params.get("upload_id"): + multipart_upload_exists = True + break + if not multipart_upload_exists: + result["msg"] = "upload id {0} does not exist.".format( + module.params.get("upload_id") + ) + return result oci_utils.call_with_backoff( - multipart_object_assembler.abort, upload_id=module.params.get("upload_id") + object_storage_client.abort_multipart_upload, + namespace_name=module.params.get("namespace_name"), + bucket_name=module.params.get("bucket_name"), + object_name=module.params.get("object_name"), + upload_id=module.params.get("upload_id"), ) result["changed"] = True return result @@ -449,6 +475,10 @@ def main(): elif state == "absent": result = delete_object(object_storage_client, module) elif state == "abort_multipart_upload": + if not module.params.get("upload_id"): + module.fail_json( + msg="upload_id required for aborting the multipart upload." + ) result = abort_multipart_upload(object_storage_client, module) else: diff --git a/library/oci_security_list.py b/library/oci_security_list.py index 548dc89..2d77192 100644 --- a/library/oci_security_list.py +++ b/library/oci_security_list.py @@ -98,6 +98,13 @@ If TCP specified as the protocol but omit this object, then all destination ports are allowed. required: no + suboptions: + destination_port_range: + description: The destination port range for the ingress rule. + Intger values for min port number and max port number should be provided. + source_port_range: + description: The source port range for the ingress rule. + Intger values for min port number and max port number should be provided. udp_options: description: Valid only for UDP. Use to specify particular destination ports for UDP rules. If UDP specified as the protocol but omit this object, then all destination ports @@ -152,6 +159,13 @@ If TCP specified as the protocol but omit this object, then all destination ports are allowed. required: no + suboptions: + destination_port_range: + description: The destination port range for the egress rule. + Intger values for min port number and max port number should be provided. + source_port_range: + description: The source port range for the egress rule. + Intger values for min port number and max port number should be provided. udp_options: description: Valid only for UDP. Use to specify particular destination ports for UDP rules. If UDP specified as the protocol but omit this object, then all destination ports @@ -200,8 +214,8 @@ protocol: '6' tcp_options: destination_port_range: - min: '22' - max: '22' + min: 22 + max: 22 - source: 'oci-iad-objectstorage' source_type: 'SERVICE_CIDR_BLOCK' is_stateless: False @@ -225,8 +239,8 @@ protocol: '6' tcp_options: destination_port_range: - min: '25' - max: '30' + min: 25 + max: 30 purge_security_rules: 'yes' state: 'present' @@ -239,8 +253,8 @@ protocol: '6' tcp_options: destination_port_range: - min: '25' - max: '30' + min: 25 + max: 30 delete_security_rules: 'yes' state: 'present' @@ -678,14 +692,14 @@ def get_protocol_option(input_protocol_options, protocol_options): ) if input_destination_port_range: port_range = oci_utils.create_hashed_instance(PortRange) - port_range.min = input_destination_port_range["min"] - port_range.max = input_destination_port_range["max"] + port_range.min = int(input_destination_port_range["min"]) + port_range.max = int(input_destination_port_range["max"]) protocol_options.destination_port_range = port_range input_source_port_range = input_protocol_options.get("source_port_range", None) if input_source_port_range: port_range = oci_utils.create_hashed_instance(PortRange) - port_range.min = input_source_port_range["min"] - port_range.max = input_source_port_range["max"] + port_range.min = int(input_source_port_range["min"]) + port_range.max = int(input_source_port_range["max"]) protocol_options.source_port_range = port_range diff --git a/library/oci_vcn.py b/library/oci_vcn.py index 4d65ae7..b3f5088 100644 --- a/library/oci_vcn.py +++ b/library/oci_vcn.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. +# Copyright (c) 2017, 2018, 2019, Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -29,10 +29,10 @@ compartment_id: description: The OCID of the compartment to contain the VCN. Required when creating a VCN with I(state=present). This option is mutually exclusive with I(vcn_id). - required: false + type: str display_name: description: A user-friendly name. Does not have to be unique, and it's changeable. - required: false + type: str aliases: [ 'name' ] dns_label: description: A DNS label for the VCN, used in conjunction with the VNIC's hostname and subnet's DNS label to @@ -40,16 +40,16 @@ bminstance-1.subnet123.vcn1.oraclevcn.com). Not required to be unique, but it's a best practice to set unique DNS labels for VCNs in your tenancy. Must be an alphanumeric string that begins with a letter. The value cannot be changed. - required: false + type: str state: description: Create or update a VCN with I(state=present). Use I(state=absent) to delete a VCN. - required: false + type: str default: present choices: ['present', 'absent'] vcn_id: description: The OCID of the VCN. Required when deleting a VCN with I(state=absent) or updating a VCN with I(state=present). This option is mutually exclusive with I(compartment_id). - required: false + type: str aliases: [ 'id' ] author: "Rohit Chaware (@rohitChaware)" extends_documentation_fragment: [ oracle, oracle_creatable_resource, oracle_wait_options, oracle_tags ] diff --git a/library/oci_waas_certificate.py b/library/oci_waas_certificate.py new file mode 100644 index 0000000..59dea72 --- /dev/null +++ b/library/oci_waas_certificate.py @@ -0,0 +1,386 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_certificate +short_description: Manage WAAS certificates in OCI +description: + - This module allows the user to create, delete and update WAAS certificates in OCI. +version_added: "2.5" +options: + compartment_id: + description: The OCID of the compartment in which to create the SSL certificate. + type: str + display_name: + description: A user-friendly name for the SSL certificate. The name can be changed and does not need to be + unique. + type: str + certificate_data: + description: The data of the SSL certificate. + type: str + private_key_data: + description: The private key data of the SSL certificate. + type: str + is_trust_verification_disabled: + description: The is_trust_verification_disabled of this certificate. Set to true if the SSL certificate + is self-signed. + type: bool + certificate_id: + description: The OCID of the SSL certificate used in the WAAS policy. Required when deleting a WAAS certificate + with I(state=absent) or updating a WAAS certificate with I(state=present). This option is mutually + exclusive with I(compartment_id). + type: str + state: + description: Create or update a WAAS certificate with I(state=present). Use I(state=absent) to delete a + WAAS certificate. + default: present + choices: ['present', 'absent'] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_creatable_resource, oracle_wait_options, oracle_tags ] +""" + +EXAMPLES = """ +- name: Create a waas certificate + oci_waas_certificate: + compartment_id: "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx" + display_name: "test_waas_certificate" + certificate_data: "{{ lookup('file', '/path/to/cert/file') }}" + private_key_data: "{{ lookup('file', '/path/to/private/key') }}" + is_trust_verification_disabled: True + +- name: Update display name of the waas certificate + oci_waas_certificate: + certificate_id: "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx" + display_name: "updated_test_waas_certificate" + +- name: Delete a waas certificate + oci_waas_certificate: + certificate_id: "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx" + state: absent +""" + +RETURN = """ +waas_certificate: + description: Information about the WAAS certificate. + returned: on successful create and update operation + type: complex + contains: + compartment_id: + description: The OCID of the certificate's compartment. + returned: success + type: str + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + defined_tags: + description: A key-value pair with a defined schema that restricts the values of tags. These predefined keys + are scoped to namespaces. + returned: success + type: str + sample: {"example_namespace": {"example_key": "example_value"}} + display_name: + description: The user-friendly name of the certificate. + returned: success + type: str + sample: testcertificate + extensions: + description: The extensions of this Certificate. + returned: success + type: list + sample: [ + { + "is_critical": null, + "name": "subjectKeyIdentifier", + "value": "A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6" + }, + { + "is_critical": null, + "name": "authorityKeyIdentifier", + "value": "keyid:A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6" + }, + { + "is_critical": true, + "name": "basicConstraints", + "value": "CA:TRUE" + } + ] + freeform_tags: + description: A simple key-value pair without any defined schema. + returned: success + type: complex + sample: {"example_freeform_key": "example_freeform_value"} + id: + description: The OCID of the certificate. + returned: success + type: str + sample: ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx + issued_by: + description: The issued_by of this Certificate. + returned: success + type: str + sample: testissuer + issuer_name: + description: The issuer_name of this Certificate. + returned: success + type: complex + sample: { + "common_name": "testcommonname", + "country": "AU", + "email_address": "test.email@address.com", + "locality": "testlocality", + "organization": "testorg", + "organizational_unit": "testorgunit", + "state_province": "teststate" + } + lifecycle_state: + description: The current lifecycle state of the SSL certificate. + returned: success + type: str + sample: ACTIVE + public_key_info: + description: The public_key_info of this Certificate. + returned: success + type: complex + sample: { + "algorithm": "RSA", + "exponent": 65537, + "key_size": 2048 + } + serial_number: + description: The serial_number of this Certificate. + returned: success + type: str + sample: 100000000000710 + signature_algorithm: + description: The signature_algorithm of this Certificate. + returned: success + type: str + sample: SHA-1 + subject_name: + description: The subject_name of this Certificate. + returned: success + type: complex + sample: { + "common_name": "testcommonname", + "country": "AU", + "email_address": "test.email@address.com", + "locality": "testlocality", + "organization": "testorg", + "organizational_unit": "testorgunit", + "state_province": "teststate" + } + time_created: + description: The date and time the certificate was created, expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2019-04-02T17:12:42.454000+00:00 + time_not_valid_after: + description: The date and time the certificate will expire, expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2020-04-01T15:29:38+00:00 + time_not_valid_before: + description: The time_not_valid_before of this Certificate. + returned: success + type: str + sample: 2019-04-02T15:29:38+00:00 + version: + description: The version of this Certificate. + returned: success + type: int + sample: 2 + sample: { + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "defined_tags": {"example_namespace": {"example_key": "example_value"}}, + "display_name": "testcertificate", + "extensions": [ + { + "is_critical": null, + "name": "subjectKeyIdentifier", + "value": "A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6" + }, + { + "is_critical": null, + "name": "authorityKeyIdentifier", + "value": "keyid:A6:B2:56:XX:XX:XX:XX:XX:XX:XX:XX:9F:E1:98:2E:8C:F6" + }, + { + "is_critical": true, + "name": "basicConstraints", + "value": "CA:TRUE" + } + ], + "freeform_tags": {"example_freeform_key": "example_freeform_value"}, + "id": "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx", + "issued_by": "testissuer", + "issuer_name": { + "common_name": "testcommonname", + "country": "AU", + "email_address": "test.email@address.com", + "locality": "testlocality", + "organization": "testorg", + "organizational_unit": "testorgunit", + "state_province": "teststate" + }, + "lifecycle_state": "ACTIVE", + "public_key_info": { + "algorithm": "RSA", + "exponent": 65537, + "key_size": 2048 + }, + "serial_number": "100000000000710", + "signature_algorithm": null, + "subject_name": { + "common_name": "testcommonname", + "country": "AU", + "email_address": "test.email@address.com", + "locality": "testlocality", + "organization": "testorg", + "organizational_unit": "testorgunit", + "state_province": "teststate" + }, + "time_created": "2019-04-13T21:51:09.088000+00:00", + "time_not_valid_after": "2020-04-01T15:29:38+00:00", + "time_not_valid_before": "2019-04-02T15:29:38+00:00", + "version": 2 + } +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils, oci_waas_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.waas.models import CreateCertificateDetails + from oci.waas.models import UpdateCertificateDetails + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + +RESOURCE_TYPE = "waas_certificate" + + +def create_certificate(waas_client, module): + create_certificate_details = CreateCertificateDetails() + for attr in create_certificate_details.attribute_map.keys(): + if attr in module.params: + setattr(create_certificate_details, attr, module.params[attr]) + result = oci_utils.create_and_wait( + resource_type=RESOURCE_TYPE, + create_fn=waas_client.create_certificate, + kwargs_create={"create_certificate_details": create_certificate_details}, + client=waas_client, + get_fn=waas_client.get_certificate, + get_param="certificate_id", + module=module, + ) + return result + + +def update_certificate(waas_client, module): + result = oci_utils.check_and_update_resource( + resource_type=RESOURCE_TYPE, + client=waas_client, + get_fn=waas_client.get_certificate, + kwargs_get={"certificate_id": module.params["certificate_id"]}, + update_fn=waas_client.update_certificate, + primitive_params_update=["certificate_id"], + kwargs_non_primitive_update={ + UpdateCertificateDetails: "update_certificate_details" + }, + module=module, + update_attributes=UpdateCertificateDetails().attribute_map.keys(), + ) + return result + + +def delete_certificate(waas_client, module): + result = oci_utils.delete_and_wait( + resource_type=RESOURCE_TYPE, + client=waas_client, + get_fn=waas_client.get_certificate, + kwargs_get={"certificate_id": module.params["certificate_id"]}, + delete_fn=waas_client.delete_certificate, + kwargs_delete={"certificate_id": module.params["certificate_id"]}, + module=module, + ) + return result + + +def main(): + module_args = oci_utils.get_taggable_arg_spec( + supports_create=True, supports_wait=True + ) + module_args.update( + dict( + compartment_id=dict(type="str", required=False), + certificate_id=dict(type="str", required=False), + display_name=dict(type="str", required=False), + certificate_data=dict(type="str", required=False), + private_key_data=dict(type="str", required=False, no_log=True), + is_trust_verification_disabled=dict(type="bool", required=False), + state=dict( + type="str", + required=False, + default="present", + choices=["absent", "present"], + ), + ) + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[("compartment_id", "certificate_id")], + ) + + waas_client = oci_utils.create_service_client(module, WaasClient) + exclude_attributes = {} + state = module.params["state"] + certificate_id = module.params.get("certificate_id") + + if state == "absent": + if not certificate_id: + module.fail_json( + msg="Specify certificate_id with state as 'absent' to delete the certificate." + ) + result = delete_certificate(waas_client, module) + + else: + if certificate_id: + result = update_certificate(waas_client, module) + else: + result = oci_utils.check_and_create_resource( + resource_type=RESOURCE_TYPE, + create_fn=create_certificate, + kwargs_create={"waas_client": waas_client, "module": module}, + list_fn=waas_client.list_certificates, + kwargs_list={"compartment_id": module.params["compartment_id"]}, + module=module, + model=CreateCertificateDetails(), + exclude_attributes=exclude_attributes, + get_resource_from_summary_fn=oci_waas_utils.get_waas_certificate_from_summary_resource, + get_resource_from_summary_fn_kwargs={"waas_client": waas_client}, + ) + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_certificate_facts.py b/library/oci_waas_certificate_facts.py new file mode 100644 index 0000000..b499b71 --- /dev/null +++ b/library/oci_waas_certificate_facts.py @@ -0,0 +1,371 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_certificate_facts +short_description: Retrieve details about WAAS certificates. +description: + - This module retrieves information of a specific WAAS certificate or lists all the WAAS certificates in the given + compartment. +version_added: "2.5" +options: + compartment_id: + description: The OCID of the compartment. + type: str + certificate_id: + description: The OCID of the SSL certificate used in the WAAS policy. Required to get information of a specific + certificate. + type: str + id: + description: Filter certificates using a list of certificates OCIDs. + type: list + display_name: + description: Filter certificates using a list of display names. + type: list + lifecycle_state: + description: Filter certificates using a list of lifecycle states. + type: list + choices: + - "CREATING" + - "ACTIVE" + - "FAILED" + - "UPDATING" + - "DELETING" + - "DELETED" + time_created_greater_than_or_equal_to: + description: A filter that matches certificates created on or after the specified date-time. + type: str + time_created_less_than: + description: A filter that matches certificates created before the specified date-time. + type: str + sort_by: + description: The value by which certificate summaries are sorted in a paginated 'List' call. + If unspecified, defaults to timeCreated. + type: str + choices: ["id", "compartmentId", "displayName", "notValidAfter", "timeCreated"] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_sort_order_option ] +""" + +EXAMPLES = """ +- name: Get all the waas certificates in a compartment + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + +- name: Get a specific waas certificate using its OCID + oci_waas_certificate_facts: + certificate_id: ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx + +- name: Get waas certificate having the specified display name + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: examplewaascertificate + +- name: Get waas certificates in a compartment with given display names + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaascertificate1 + - examplewaascertificate2 + +- name: Filter waas certificates in a compartment using display_name, lifecycle_state and sort the results + oci_waas_certificate_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaascertificate1 + - examplewaascertificate2 + lifecycle_state: + - ACTIVE + sort_by: timeCreated + sort_order: DESC +""" + +RETURN = """ +waas_certificates: + description: List of waas certificates + returned: on success + type: complex + contains: + compartment_id: + description: The OCID of the certificate's compartment. + returned: success + type: str + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + defined_tags: + description: A key-value pair with a defined schema that restricts the values of tags. These predefined keys + are scoped to namespaces. + returned: success + type: str + sample: {"example_namespace": {"example_key": "example_value"}} + display_name: + description: The user-friendly name of the certificate. + returned: success + type: str + sample: testcertificate + extensions: + description: The extensions of this Certificate. + returned: success + type: list + sample: [{"is_critical": null, "name": "subjectKeyIdentifier", "value": "A6:B2:56:1X:1X:1X:1X:8C:F6"}] + freeform_tags: + description: A simple key-value pair without any defined schema. + returned: success + type: complex + sample: {"example_freeform_key": "example_freeform_value"} + id: + description: The OCID of the certificate. + returned: success + type: str + sample: ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx + issued_by: + description: The issued_by of this Certificate. + returned: success + type: str + sample: testissuer + issuer_name: + description: The issuer_name of this Certificate. + returned: success + type: complex + sample: { + "common_name": "testcommonname", + "country": "AU", + "email_address": "test.email@address.com", + "locality": "testlocality", + "organization": "testorg", + "organizational_unit": "testorgunit", + "state_province": "teststate" + } + lifecycle_state: + description: The current lifecycle state of the SSL certificate. + returned: success + type: str + sample: ACTIVE + public_key_info: + description: The public_key_info of this Certificate. + returned: success + type: complex + sample: { + "algorithm": "RSA", + "exponent": 65537, + "key_size": 2048 + } + serial_number: + description: The serial_number of this Certificate. + returned: success + type: str + sample: 100000000000710 + signature_algorithm: + description: The signature_algorithm of this Certificate. + returned: success + type: str + sample: SHA-1 + subject_name: + description: The subject_name of this Certificate. + returned: success + type: complex + sample: { + "common_name": "testcommonname", + "country": "AU", + "email_address": "test.email@address.com", + "locality": "testlocality", + "organization": "testorg", + "organizational_unit": "testorgunit", + "state_province": "teststate" + } + time_created: + description: The date and time the certificate was created, expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2019-04-02T17:12:42.454000+00:00 + time_not_valid_after: + description: The date and time the certificate will expire, expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2020-04-01T15:29:38+00:00 + time_not_valid_before: + description: The time_not_valid_before of this Certificate. + returned: success + type: str + sample: 2019-04-02T15:29:38+00:00 + version: + description: The version of this Certificate. + returned: success + type: int + sample: 2 + sample: [ + { + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "defined_tags": null, + "display_name": "test waas certificate", + "extensions": null, + "freeform_tags": null, + "id": "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx", + "issued_by": "Ansible", + "issuer_name": { + "common_name": "testcommonname", + "country": "IN", + "email_address": null, + "locality": "Bangalore", + "organization": "Ansible", + "organizational_unit": null, + "state_province": "KA" + }, + "lifecycle_state": "ACTIVE", + "public_key_info": { + "algorithm": "RSA", + "exponent": 65537, + "key_size": 2048 + }, + "serial_number": "9917593779878295042", + "signature_algorithm": null, + "subject_name": { + "common_name": "testcommonname", + "country": "IN", + "email_address": null, + "locality": "Bangalore", + "organization": "Ansible", + "organizational_unit": null, + "state_province": "KA" + }, + "time_created": "2019-04-10T10:05:35.634000+00:00", + "time_not_valid_after": "2024-04-08T08:09:17+00:00", + "time_not_valid_before": "2019-04-10T08:09:17+00:00", + "version": null + } + ] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_certificates(waas_client, module): + if not module.params.get("compartment_id"): + module.fail_json(msg="compartment_id required to list certificates.") + optional_list_method_params = [ + "sort_by", + "sort_order", + "id", + "display_name", + "lifecycle_state", + "time_created_greater_than_or_equal_to", + "time_created_less_than", + ] + optional_kwargs = dict( + (param, module.params[param]) + for param in optional_list_method_params + if module.params.get(param) is not None + ) + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_certificate, certificate_id=certificate.id + ).data + for certificate in oci_utils.list_all_resources( + waas_client.list_certificates, + compartment_id=module.params["compartment_id"], + **optional_kwargs + ) + ] + ) + + +def get_certificate(waas_client, module): + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_certificate, + certificate_id=module.params["certificate_id"], + ).data + ] + ) + + +def main(): + module_args = oci_utils.get_facts_module_arg_spec( + filter_by_display_name=False, + supports_sort=True, + sort_by_choices=[ + "id", + "compartmentId", + "displayName", + "notValidAfter", + "timeCreated", + ], + ) + module_args.update( + dict( + certificate_id=dict(type="str"), + compartment_id=dict(type="str"), + display_name=dict(type="list"), + id=dict(type="list"), + lifecycle_state=dict( + type="list", + choices=[ + "CREATING", + "ACTIVE", + "FAILED", + "UPDATING", + "DELETING", + "DELETED", + ], + ), + time_created_greater_than_or_equal_to=dict(type="str"), + time_created_less_than=dict(type="str"), + ) + ) + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[["certificate_id", "compartment_id"]], + ) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + waas_client = oci_utils.create_service_client(module, WaasClient) + + try: + if module.params["certificate_id"]: + result = get_certificate(waas_client, module) + elif module.params["compartment_id"]: + result = list_certificates(waas_client, module) + else: + module.fail_json( + msg="Specify a compartment_id to get all the certificates in the compartment or certificate_id " + "to retrieve a specific certificate." + ) + except ServiceError as se: + module.fail_json(msg=se.message) + + module.exit_json(waas_certificates=result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_edge_subnet_facts.py b/library/oci_waas_edge_subnet_facts.py new file mode 100644 index 0000000..e1beaf2 --- /dev/null +++ b/library/oci_waas_edge_subnet_facts.py @@ -0,0 +1,123 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_edge_subnet_facts +short_description: Retrieve facts of subnets corresponding the Web Application Firewall. +description: + - Returns a list of subnets corresponding the Web Application Firewall. Return the list of the tenant's edge node + subnets. Use these CIDR blocks to restrict incoming traffic to your origin. These subnets are owned by OCI and + forward traffic to customer origins. They are not associated with specific regions or compartments. +version_added: "2.5" +options: + sort_by: + description: The value by which edge node subnets are sorted. + choices: ["cidr", "region", "timeModified"] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_sort_order_option ] +""" + +EXAMPLES = """ +- name: Get all the edge subnets + oci_waas_edge_subnet_facts: + +- name: Get all the edge subnets sorted by region + oci_waas_edge_subnet_facts: + sort_by: region + sort_order: DESC +""" + +RETURN = """ +waas_edge_subnets: + description: List of the tenant's edge node subnets. + returned: on success + type: complex + contains: + cidr: + description: CIDR of an edge node subnet. This can include /24 or /8 addresses. + returned: success + type: str + sample: 52.28.32.104 + region: + description: The name of the region containing the indicated subnet. + returned: success + type: str + sample: Europe + time_modified: + description: The date and time the last change was made to the indicated edge node subnet, expressed in + RFC 3339 timestamp format. + returned: success + type: str + sample: 2017-01-30T13:27:08+00:00 + sample: [{ + "cidr": "52.28.32.104", + "region": "Europe", + "time_modified": "2017-01-30T13:27:08+00:00" + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_edge_subnets(waas_client, module): + optional_list_method_params = ["sort_by", "sort_order"] + optional_kwargs = dict( + (param, module.params[param]) + for param in optional_list_method_params + if module.params.get(param) is not None + ) + return to_dict( + oci_utils.list_all_resources(waas_client.list_edge_subnets, **optional_kwargs) + ) + + +def main(): + module_args = oci_utils.get_facts_module_arg_spec( + filter_by_display_name=False, + supports_sort=True, + sort_by_choices=["cidr", "region", "timeModified"], + ) + + module = AnsibleModule(argument_spec=module_args, supports_check_mode=False) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + waas_client = oci_utils.create_service_client(module, WaasClient) + try: + result = list_edge_subnets(waas_client, module) + except ServiceError as se: + module.fail_json(msg=se.message) + + module.exit_json(waas_edge_subnets=result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_policy.py b/library/oci_waas_policy.py new file mode 100644 index 0000000..87f0bdb --- /dev/null +++ b/library/oci_waas_policy.py @@ -0,0 +1,1007 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +module: oci_waas_policy +short_description: Manage WAAS policies in OCI +description: + - This module allows the user to create, delete and update WAAS policies in OCI. +version_added: "2.5" +options: + compartment_id: + description: The OCID of the compartment. + type: str + display_name: + description: A user-friendly name for the WAAS policy. The name is can be changed and does not need to + be unique. + type: str + aliases: [ 'name' ] + domain: + description: The web application domain that the WAAS policy protects. + type: str + additional_domains: + description: An array of additional domains for the specified web application. + type: list + origins: + description: A map of host to origin for the web application. The key should be a customer friendly name for + the host, ex. primary, secondary, etc. + type: dict + suboptions: + custom_headers: + description: A list of HTTP headers to forward to your origin. + suboptions: + name: + description: The name of the header. + value: + description: The value of the header. + http_port: + description: The HTTP port on the origin that the web application listens on. If unspecified, defaults + to 80. + https_port: + description: The HTTPS port on the origin that the web application listens on. If unspecified, defaults + to 443. + uri: + description: The URI of the origin. Does not support paths. Port numbers should be specified in the + http_port and https_port fields. + policy_config: + description: Config for the WAAS policy. + type: dict + suboptions: + certificate_id: + description: The OCID of the SSL certificate to use if HTTPS is supported. + is_https_enabled: + description: Enable or disable HTTPS support. If true, a certificateId is required. + default: False + is_https_forced: + description: Force HTTP to HTTPS redirection. + default: False + waf_config: + description: The WAF config for the WAAS policy. + type: dict + suboptions: + access_rules: + description: The access rules applied to the Web Application Firewall. Used for defining custom access + policies with the combination of ALLOW, DETECT, and BLOCK rules, based on different + criteria. + suboptions: + action: + description: The action to take when the access criteria are met for a rule. + default: ALLOW + block_action: + description: The method used to block requests if I(action=BLOCK) and the access criteria + are met. + choices: + - SET_RESPONSE_CODE + - SHOW_ERROR_PAGE + default: SET_RESPONSE_CODE + block_error_page_code: + description: The error code to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the access criteria are met. + default: Access rules + block_error_page_description: + description: The description text to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the access criteria are met. + default: Access blocked by website owner. Please contact support. + block_error_page_message: + description: The message to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the access criteria are met. + default: Access to the website is blocked. + block_response_code: + description: The response status code to return when I(action=BLOCK), + I(block_action=SET_RESPONSE_CODE), and the access criteria are met. + default: 403 + criteria: + description: The list of access rule criteria. + suboptions: + condition: + description: The criteria the access rule uses to determine if action should be taken + on a request. + required: true + value: + description: The criteria value. + required: true + choices: ["URL_IS", "URL_IS_NOT", "URL_STARTS_WITH", "URL_PART_ENDS_WITH", + "URL_PART_CONTAINS", "URL_REGEX", "IP_IS", "IP_IS_NOT", "HTTP_HEADER_CONTAINS", + "COUNTRY_IS", "COUNTRY_IS_NOT", "USER_AGENT_IS", "USER_AGENT_IS_NOT"] + name: + description: The unique name of the access rule. + address_rate_limiting: + description: The IP address rate limiting settings used to limit the number of requests from an address. + suboptions: + allowed_rate_per_address: + description: The number of allowed requests per second from one IP address. + default: 1 + block_response_code: + description: The response status code returned when a request is blocked. + default: 503 + is_enabled: + description: Enables or disables the address rate limiting Web Application Firewall feature. + max_delayed_count_per_address: + description: The maximum number of requests allowed to be queued before subsequent requests + are dropped. + default: 10 + captchas: + description: A list of CAPTCHA challenge settings. These are used to challenge requests with a CAPTCHA + to block bots. + suboptions: + failure_message: + description: The text to show when incorrect CAPTCHA text is entered. + required: true + footer_text: + description: The text to show in the footer when showing a CAPTCHA challenge. + default: Enter the letters and numbers as they are shown in the image above. + header_text: + description: The text to show in the header when showing a CAPTCHA challenge. + default: We have detected an increased number of attempts to access this website. + To help us keep this site secure, please let us know that you are not a robot by + entering the text from the image below. + session_expiration_in_seconds: + description: The amount of time before the CAPTCHA expires, in seconds. + required: true + submit_label: + description: The text to show on the label of the CAPTCHA challenge submit button. + required: true + title: + description: The title used when displaying a CAPTCHA challenge. + required: true + url: + description: The unique URL path at which to show the CAPTCHA challenge. + required: true + device_fingerprint_challenge: + description: The device fingerprint challenge settings. Used to detect unique devices based on the + device fingerprint information collected in order to block bots. + suboptions: + action: + description: The action to take on requests from detected bots. + choices: + - DETECT + - BLOCK + default: DETECT + action_expiration_in_seconds: + description: The number of seconds between challenges for the same IP address. + default: 60 + challenge_settings: + description: The challenge settings. + suboptions: + block_action: + description: The method used to block requests that fail the challenge if + I(action=BLOCK). + choices: + - SET_RESPONSE_CODE + - SHOW_ERROR_PAGE + - SHOW_CAPTCHA + default: SHOW_ERROR_PAGE + block_error_page_code: + description: The error code to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: 403 + block_error_page_description: + description: The description text to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: Access blocked by website owner. Please contact support. + block_error_page_message: + description: The message to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: Access to the website is blocked. + block_response_code: + description: The response status code to return when I(action=BLOCK), + I(block_action=SET_RESPONSE_CODE), and the request is blocked. + default: 403 + captcha_footer: + description: The text to show in the footer when showing a CAPTCHA challenge when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Enter the letters and numbers as they are shown in image above. + captcha_header: + description: The text to show in the header when showing a CAPTCHA challenge when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: We have detected an increased number of attempts to access this webapp. + To help us keep this webapp secure, please let us know that you are not a robot + by entering the text from captcha below. + captcha_submit_label: + description: The text to show on the label of the CAPTCHA challenge submit button when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Yes, I am human. + captcha_title: + description: The title used when showing a CAPTCHA challenge when I(action=BLOCK), + I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Are you human? + failure_threshold: + description: The number of failed requests allowed before taking action. + default: 10 + failure_threshold_expiration_in_seconds: + description: The number of seconds before the failure threshold resets. + default: 60 + is_enabled: + description: Enables or disables the device fingerprint challenge Web Application Firewall + feature. + max_address_count: + description: The maximum number of IP addresses permitted with the same device fingerprint. + default: 20 + max_address_count_expiration_in_seconds: + description: The number of seconds before the maximum addresses count resets. + default: 60 + good_bots: + description: A list of bots allowed to access the web application. + suboptions: + description: + description: The description of the bot. + is_enabled: + description: Enables or disables the bot. + key: + description: The unique key for the bot. + name: + description: The bot name. + human_interaction_challenge: + description: The human interaction challenge settings. Used to look for natural human interactions such + as mouse movements, time on site, and page scrolling to identify bots. + suboptions: + action: + description: The action to take on requests from detected bots. + choices: + - DETECT + - BLOCK + default: DETECT + action_expiration_in_seconds: + description: The number of seconds between challenges for the same IP address. + default: 60 + challenge_settings: + description: The challenge settings. + suboptions: + block_action: + description: The method used to block requests that fail the challenge if + I(action=BLOCK). + choices: + - SET_RESPONSE_CODE + - SHOW_ERROR_PAGE + - SHOW_CAPTCHA + default: SHOW_ERROR_PAGE + block_error_page_code: + description: The error code to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: 403 + block_error_page_description: + description: The description text to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: Access blocked by website owner. Please contact support. + block_error_page_message: + description: The message to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: Access to the website is blocked. + block_response_code: + description: The response status code to return when I(action=BLOCK), + I(block_action=SET_RESPONSE_CODE), and the request is blocked. + default: 403 + captcha_footer: + description: The text to show in the footer when showing a CAPTCHA challenge when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Enter the letters and numbers as they are shown in image above. + captcha_header: + description: The text to show in the header when showing a CAPTCHA challenge when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: We have detected an increased number of attempts to access this webapp. + To help us keep this webapp secure, please let us know that you are not a robot + by entering the text from captcha below. + captcha_submit_label: + description: The text to show on the label of the CAPTCHA challenge submit button when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Yes, I am human. + captcha_title: + description: The title used when showing a CAPTCHA challenge when I(action=BLOCK), + I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Are you human? + failure_threshold: + description: The number of failed requests allowed before taking action. + default: 10 + failure_threshold_expiration_in_seconds: + description: The number of seconds before the failure threshold resets. + default: 60 + interaction_threshold: + description: The number of interactions required to pass the challenge. + default: 3 + is_enabled: + description: Enables or disables the human interaction challenge Web Application Firewall + feature. + recording_period_in_seconds: + description: The number of seconds to record the interactions from the user. + default: 15 + set_http_header: + description: Adds an additional HTTP header to requests that fail the challenge before being + passed to the origin. Only applicable when I(action=DETECT). + suboptions: + name: + description: The name of the header. + value: + description: The value of the header. + js_challenge: + description: The JavaScript challenge settings. Used to challenge requests with a JavaScript challenge + and take the action if a browser has no JavaScript support in order to block bots. + suboptions: + action: + description: The action to take against requests from detected bots. + choices: + - DETECT + - BLOCK + default: DETECT + action_expiration_in_seconds: + description: The number of seconds between challenges from the same IP address. + default: 60 + challenge_settings: + description: The challenge settings. + suboptions: + block_action: + description: The method used to block requests that fail the challenge if + I(action=BLOCK). + choices: + - SET_RESPONSE_CODE + - SHOW_ERROR_PAGE + - SHOW_CAPTCHA + default: SHOW_ERROR_PAGE + block_error_page_code: + description: The error code to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: 403 + block_error_page_description: + description: The description text to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: Access blocked by website owner. Please contact support. + block_error_page_message: + description: The message to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the request is blocked. + default: Access to the website is blocked. + block_response_code: + description: The response status code to return when I(action=BLOCK), + I(block_action=SET_RESPONSE_CODE), and the request is blocked. + default: 403 + captcha_footer: + description: The text to show in the footer when showing a CAPTCHA challenge when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Enter the letters and numbers as they are shown in image above. + captcha_header: + description: The text to show in the header when showing a CAPTCHA challenge when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: We have detected an increased number of attempts to access this webapp. + To help us keep this webapp secure, please let us know that you are not a robot + by entering the text from captcha below. + captcha_submit_label: + description: The text to show on the label of the CAPTCHA challenge submit button when + I(action=BLOCK), I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Yes, I am human. + captcha_title: + description: The title used when showing a CAPTCHA challenge when I(action=BLOCK), + I(block_action=SHOW_CAPTCHA), and the request is blocked. + default: Are you human? + failure_threshold: + description: The number of failed requests before taking action. + default: 10 + is_enabled: + description: Enables or disables the JavaScript challenge Web Application Firewall feature. + required: true + set_http_header: + description: Adds an additional HTTP header to requests that fail the challenge before being + passed to the origin. Only applicable when I(action=DETECT). + suboptions: + name: + description: The name of the header. + value: + description: The value of the header. + origin: + description: The key in the map of origins referencing the origin used for the Web Application Firewall. + The origin must already be included in Origins. Required when creating the WafConfig + resource, but not on update. + protection_rules: + description: A list of the protection rules and their details. + suboptions: + action: + description: The action to take when the traffic is detected as malicious. + default: OFF + description: + description: The description of the protection rule. + exclusions: + description: The exclusions of this ProtectionRule. + suboptions: + exclusions: + description: The exclusions of this ProtectionRuleExclusion. + target: + description: The target of the exclusion. + choices: + - REQUEST_COOKIES + - REQUEST_COOKIE_NAMES + - ARGS + - ARGS_NAMES + key: + description: The unique key of the protection rule. + labels: + description: The list of labels for the protection rule. + mod_security_rule_ids: + description: The list of the ModSecurity rule IDs that apply to this protection rule. + name: + description: The name of the protection rule. + protection_settings: + description: The settings to apply to protection rules. + suboptions: + allowed_http_methods: + description: The list of allowed HTTP methods. If unspecified, default to [OPTIONS, GET, HEAD, POST]. + choices: ["OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "PATCH", + "PROPFIND"] + default: ["OPTIONS", "GET", "HEAD", "POST"] + block_action: + description: If I(action=BLOCK), this specifies how the traffic is blocked when detected as + malicious by a protection rule. + choices: + - SHOW_ERROR_PAGE + - SET_RESPONSE_CODE + default: SET_RESPONSE_CODE + block_error_page_code: + description: The error code to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the traffic is detected as malicious by a + protection rule. + default: 403 + block_error_page_description: + description: The description text to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the traffic is detected as malicious by a + protection rule. + default: Access blocked by website owner. Please contact support. + block_error_page_message: + description: The message to show on the error page when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the traffic is detected as malicious by a + protection rule. + default: Access to the website is blocked. + block_response_code: + description: The response code returned when I(action=BLOCK), + I(block_action=SHOW_ERROR_PAGE), and the traffic is detected as malicious by a + protection rule. + default: 403 + is_response_inspected: + description: Inspects the response body of origin responses. Can be used to detect leakage of + sensitive data. + default: false + max_argument_count: + description: The maximum number of arguments allowed to be passed to your application before + an action is taken. + default: 255 + max_name_length_per_argument: + description: The maximum length allowed for each argument name, in characters. + default: 400 + max_response_size_in_ki_b: + description: The maximum response size to be fully inspected, in binary kilobytes (KiB). + Anything over this limit will be partially inspected. + default: 1024 + max_total_name_length_of_arguments: + description: The maximum length allowed for the sum of all argument names, in characters. + default: 64000 + media_types: + description: The list of media types to allow for inspection, if I(is_response_inspected=True). + Only responses with MIME types in this list will be inspected. + default: ["text/html", "text/plain", "text/xml"] + recommendations_period_in_days: + description: The length of time to analyze traffic, in days. After the analysis period, + WafRecommendations will be populated. + default: 10 + threat_feeds: + description: A list of threat intelligence feeds and the actions to apply to known malicious traffic + based on internet intelligence. + suboptions: + action: + description: The action to take when traffic is flagged as malicious by data from the threat + intelligence feed. + choices: + - OFF + - DETECT + - BLOCK + default: OFF + description: + description: The description of the threat intelligence feed. + key: + description: The unique key of the threat intelligence feed. + name: + description: The name of the threat intelligence feed. + whitelists: + description: A list of IP addresses that bypass the Web Application Firewall. + suboptions: + addresses: + description: A set of IP addresses or CIDR notations to include in the whitelist. + required: true + name: + description: The unique name of the whitelist. + required: true + state: + description: Create or update a WAAS policy with I(state=present). Use I(state=absent) to delete a WAAS policy. + default: present + choices: ['present', 'absent'] + waas_policy_id: + description: The OCID of the WAAS policy. Required when deleting a WAAS policy with I(state=absent) or updating + a WAAS policy with I(state=present). This option is mutually exclusive with I(compartment_id). + required: false + aliases: [ 'id' ] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_creatable_resource, oracle_wait_options, oracle_tags ] +""" + +EXAMPLES = """ +- name: Create a WAAS policy + oci_waas_policy: + cidr_block: '10.0.0.0/16' + compartment_id: 'ocid1.compartment.oc1..xxxxxEXAMPLExxxxx' + display_name: my_vcn + dns_label: ansiblevcn + +- name: Updates the specified VCN's display name + oci_vcn: + vcn_id: ocid1.vcn.oc1.phx.xxxxxEXAMPLExxxxx + display_name: ansible_vcn + +- name: Delete the specified VCN + oci_vcn: + vcn_id: ocid1.vcn.oc1.phx.xxxxxEXAMPLExxxxx + state: absent +""" + +RETURN = """ +waas_policy: + description: List of waas policies + returned: on success + type: complex + contains: + additional_domains: + description: An array of additional domains for this web application. + returned: success + type: list + sample: ["www.exampledomain1.com", "www.exampledomain2.com"] + cname: + description: The CNAME record to add to your DNS configuration to route traffic for the domain, and all + additional domains, through the WAF. + returned: success + type: str + sample: www-exampledomain-com.b.waas.oci.oraclecloud.net + compartment_id: + description: The OCID of the WAAS policy's compartment. + returned: success + type: str + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + defined_tags: + description: A key-value pair with a defined schema that restricts the values of tags. These predefined keys + are scoped to namespaces. + returned: success + type: complex + sample: {"example_namespace": {"example_key": "example_value"}} + display_name: + description: The user-friendly name of the WAAS policy. + returned: success + type: str + sample: examplewaaspolicy1 + domain: + description: The web application domain that the WAAS policy protects. + returned: success + type: str + sample: "www.exampledomain.com" + freeform_tags: + description: A simple key-value pair without any defined schema. + returned: success + type: complex + sample: {"example_freeform_key": "example_freeform_value"} + id: + description: The OCID of the WAAS policy. + returned: success + type: str + sample: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + lifecycle_state: + description: The current lifecycle state of the WAAS policy. + returned: success + type: str + sample: ACTIVE + origins: + description: A map of host to origin for the web application. + returned: success + type: complex + sample: {"LBaaS": {"custom_headers": [], "http_port": 80, "https_port": 443, "uri": "1.2.3.4"}} + policy_config: + description: The policy_config of the WaasPolicy. + returned: success + type: complex + sample: {"certificate_id": null, "is_https_enabled": false, "is_https_forced": false} + time_created: + description: The date and time the policy was created, expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2019-03-22T13:02:55.563000+00:00 + waf_config: + description: The waf_config of this WaasPolicy. + returned: success + type: complex + sample: { + "access_rules": [], + "address_rate_limiting": { + "allowed_rate_per_address": 1, + "block_response_code": 503, + "is_enabled": false, + "max_delayed_count_per_address": 10 + }, + "captchas": [], + "device_fingerprint_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "DFC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "is_enabled": false, + "max_address_count": 20, + "max_address_count_expiration_in_seconds": 60 + }, + "good_bots": [ + { + "description": "Googlebot is the search bot software used by Google", + "is_enabled": false, + "key": "4a4c6e7b-4d89-4141-8555-ec3b22b90a73", + "name": "Googlebot " + }, + ], + "human_interaction_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "HIC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "interaction_threshold": 3, + "is_enabled": false, + "recording_period_in_seconds": 15, + "set_http_header": null + }, + "js_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "JSC-403", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "is_enabled": false, + "set_http_header": { + "name": "x-jsc-alerts", + "value": "{failed_amount}" + } + }, + "origin": "LBaaS", + "protection_rules": [ + { + "action": "OFF", + "description": "Cross-Site Scripting (XSS) Attempt: XSS Filters from IE", + "exclusions": [], + "key": "941340", + "labels": [ + "OWASP", + "OWASP-2017", + "CRS3", + "WASCTC", + "PCI", + "HTTP", + "A2", + "A2-2017", + "XSS", + "Cross-Site Scripting" + ], + "mod_security_rule_ids": [ + "941340" + ], + "name": "Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer" + }, + ], + "whitelists": []} + sample: [{ + "additional_domains": ["www.exampledomain1.com", "www.exampledomain2.com"], + "cname": "www-exampledomain-com.b.waas.oci.oraclecloud.net", + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "defined_tags": {"example_namespace": {"example_key": "example_value"}}, + "display_name": "ansible_test_waas_policy", + "domain": "www.example.com", + "freeform_tags": {"example_freeform_key": "example_freeform_value"}, + "id": "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx", + "lifecycle_state": "ACTIVE", + "origins": {"LBaaS": {"custom_headers": [], "http_port": 80, "https_port": 443, "uri": "1.2.3.4"}}, + "policy_config": {"certificate_id": null, "is_https_enabled": false, "is_https_forced": false}, + "time_created": "2019-03-22T13:02:55.563000+00:00", + "waf_config": { + "access_rules": [], + "address_rate_limiting": { + "allowed_rate_per_address": 1, + "block_response_code": 503, + "is_enabled": false, + "max_delayed_count_per_address": 10 + }, + "captchas": [], + "device_fingerprint_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "DFC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "is_enabled": false, + "max_address_count": 20, + "max_address_count_expiration_in_seconds": 60 + }, + "good_bots": [ + { + "description": "Googlebot is the search bot software used by Google.", + "is_enabled": false, + "key": "4a4c6e7b-4d89-4141-8555-ec3b22b90a73", + "name": "Googlebot " + }, + ], + "human_interaction_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "HIC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "interaction_threshold": 3, + "is_enabled": false, + "recording_period_in_seconds": 15, + "set_http_header": null + }, + "js_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "JSC-403", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "is_enabled": false, + "set_http_header": { + "name": "x-jsc-alerts", + "value": "{failed_amount}" + } + }, + "origin": "LBaaS", + "protection_rules": [ + { + "action": "OFF", + "description": "Cross-Site Scripting (XSS) Attempt: XSS Filters from IE", + "exclusions": [], + "key": "941340", + "labels": [ + "OWASP", + "OWASP-2017", + "CRS3", + "WASCTC", + "PCI", + "HTTP", + "A2", + "A2-2017", + "XSS", + "Cross-Site Scripting" + ], + "mod_security_rule_ids": [ + "941340" + ], + "name": "Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer" + }, + ], + "whitelists": []} + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils, oci_waas_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.waas.models import CreateWaasPolicyDetails + from oci.waas.models import UpdateWaasPolicyDetails + from oci.util import to_dict + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + +RESOURCE_TYPE = "waas_policy" + + +def create_waas_policy(waas_client, module): + create_waas_policy_details = oci_waas_utils.get_waas_policy_create_model(module) + result = oci_utils.create_and_wait_on_work_request( + resource_type=RESOURCE_TYPE, + create_fn=waas_client.create_waas_policy, + kwargs_create={"create_waas_policy_details": create_waas_policy_details}, + module=module, + client=waas_client, + get_resource_from_work_request_response_fn=oci_waas_utils.get_waas_policy_from_work_request_response, + ) + return result + + +def update_waas_policy(waas_client, module): + origins = oci_waas_utils.get_waas_origins(module) + policy_config = oci_waas_utils.get_waas_policy_config(module) + waf_config = oci_waas_utils.get_waf_config_for_update(module) + result = oci_utils.check_and_update_resource( + resource_type=RESOURCE_TYPE, + client=waas_client, + get_fn=waas_client.get_waas_policy, + kwargs_get={"waas_policy_id": module.params["waas_policy_id"]}, + update_fn=waas_client.update_waas_policy, + primitive_params_update=["waas_policy_id"], + kwargs_non_primitive_update={ + UpdateWaasPolicyDetails: "update_waas_policy_details" + }, + module=module, + update_attributes=UpdateWaasPolicyDetails().attribute_map.keys(), + sub_attributes_of_update_model={ + "origins": origins, + "policy_config": policy_config, + "waf_config": waf_config, + }, + ) + return result + + +def delete_waas_policy(waas_client, module): + result = oci_utils.delete_and_wait( + resource_type=RESOURCE_TYPE, + client=waas_client, + get_fn=waas_client.get_waas_policy, + kwargs_get={"waas_policy_id": module.params["waas_policy_id"]}, + delete_fn=waas_client.delete_waas_policy, + kwargs_delete={"waas_policy_id": module.params["waas_policy_id"]}, + module=module, + ) + return result + + +def list_waas_policies(waas_client, module): + if not module.params.get("compartment_id"): + module.fail_json("compartment_id required to list waas policies.") + compartment_id = module.params["compartment_id"] + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_waas_policy, waas_policy_id=waas_policy.id + ).data + for waas_policy in oci_utils.list_all_resources( + waas_client.list_waas_policies, compartment_id=compartment_id + ) + ] + ) + + +def main(): + module_args = oci_utils.get_taggable_arg_spec( + supports_create=True, supports_wait=True + ) + module_args.update( + dict( + compartment_id=dict(type="str", required=False), + display_name=dict(type="str", required=False, aliases=["name"]), + domain=dict(type="str", required=False), + additional_domains=dict(type="list", required=False), + origins=dict(type="dict", required=False), + policy_config=dict(type="dict", required=False), + waf_config=dict(type="dict", required=False), + state=dict( + type="str", + required=False, + default="present", + choices=["absent", "present"], + ), + waas_policy_id=dict(type="str", required=False, aliases=["id"]), + ) + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[("compartment_id", "waas_policy_id")], + ) + + waas_client = oci_utils.create_service_client(module, WaasClient) + exclude_attributes = {"display_name": True} + exclude_attributes_even_when_user_provides_value = {"waf_config": True} + state = module.params["state"] + waas_policy_id = module.params["waas_policy_id"] + + if state == "absent": + if not waas_policy_id: + module.fail_json( + msg="Specify waas_policy_id with state as 'absent' to delete the waas policy." + ) + result = delete_waas_policy(waas_client, module) + + else: + if waas_policy_id: + result = update_waas_policy(waas_client, module) + else: + result = oci_utils.check_and_create_resource( + resource_type="waas_policy", + create_fn=create_waas_policy, + kwargs_create={"waas_client": waas_client, "module": module}, + list_fn=waas_client.list_waas_policies, + kwargs_list={"compartment_id": module.params["compartment_id"]}, + module=module, + model=CreateWaasPolicyDetails(), + exclude_attributes=exclude_attributes, + exclude_attributes_even_when_user_provides_value=exclude_attributes_even_when_user_provides_value, + default_attribute_values={ + "policy_config": { + "certificate_id": None, + "is_https_enabled": False, + "is_https_forced": False, + } + }, + get_resource_from_summary_fn=oci_waas_utils.get_waas_policy_from_summary_resource, + get_resource_from_summary_fn_kwargs={"waas_client": waas_client}, + ) + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_policy_facts.py b/library/oci_waas_policy_facts.py new file mode 100644 index 0000000..599d7a4 --- /dev/null +++ b/library/oci_waas_policy_facts.py @@ -0,0 +1,487 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_policy_facts +short_description: Retrieve details about WAAS Policies. +description: + - This module retrieves information of a specific WAAS policy or lists all WAAS policies in the given compartment. +version_added: "2.5" +options: + compartment_id: + description: The OCID of the compartment. + type: str + waas_policy_id: + description: The OCID of the WAAS policy. Required to get information of a specific waas policy. + type: str + id: + description: Filter policies using a list of policy OCIDs. + type: list + display_name: + description: Filter policies using a list of display names. + type: list + lifecycle_state: + description: Filter policies using a list of lifecycle states. + type: list + time_created_greater_than_or_equal_to: + description: A filter that matches policies created on or after the specified date and time. + type: str + time_created_less_than: + description: A filter that matches policies created before the specified date-time. + type: str + sort_by: + description: The value by which policies are sorted in a paginated 'List' call. If unspecified, + defaults to timeCreated. + type: str + choices: ["id", "displayName", "timeCreated"] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_sort_order_option ] +""" + +EXAMPLES = """ +- name: Get all the waas policies in a compartment + oci_waas_policy_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + +- name: Get a specific waas policy using its OCID + oci_waas_policy_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + +- name: Get waas policy having the specified display name + oci_waas_policy_facts: + display_name: examplewaaspolicy + +- name: Get waas policies in a compartment with given display names + oci_waas_policy_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaaspolicy1 + - examplewaaspolicy2 + +- name: Filter waas policies in a compartment using display_name, lifecycle_state and sort the results + oci_waas_policy_facts: + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + display_name: + - examplewaaspolicy1 + - examplewaaspolicy2 + lifecycle_state: + - AVAILABLE + sort_by: timeCreated + sort_order: DESC +""" + +RETURN = """ +waas_policies: + description: List of waas policies + returned: on success + type: complex + contains: + additional_domains: + description: An array of additional domains for this web application. + returned: success + type: list + sample: ["www.exampledomain1.com", "www.exampledomain2.com"] + cname: + description: The CNAME record to add to your DNS configuration to route traffic for the domain, and all + additional domains, through the WAF. + returned: success + type: str + sample: www-exampledomain-com.b.waas.oci.oraclecloud.net + compartment_id: + description: The OCID of the WAAS policy's compartment. + returned: success + type: str + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + defined_tags: + description: A key-value pair with a defined schema that restricts the values of tags. These predefined keys + are scoped to namespaces. + returned: success + type: complex + sample: {"example_namespace": {"example_key": "example_value"}} + display_name: + description: The user-friendly name of the WAAS policy. + returned: success + type: str + sample: examplewaaspolicy1 + domain: + description: The web application domain that the WAAS policy protects. + returned: success + type: str + sample: "www.exampledomain.com" + freeform_tags: + description: A simple key-value pair without any defined schema. + returned: success + type: complex + sample: {"example_freeform_key": "example_freeform_value"} + id: + description: The OCID of the WAAS policy. + returned: success + type: str + sample: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + lifecycle_state: + description: The current lifecycle state of the WAAS policy. + returned: success + type: str + sample: ACTIVE + origins: + description: A map of host to origin for the web application. + returned: success + type: complex + sample: {"LBaaS": {"custom_headers": [], "http_port": 80, "https_port": 443, "uri": "1.2.3.4"}} + policy_config: + description: The policy_config of the WaasPolicy. + returned: success + type: complex + sample: {"certificate_id": null, "is_https_enabled": false, "is_https_forced": false} + time_created: + description: The date and time the policy was created, expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2019-03-22T13:02:55.563000+00:00 + waf_config: + description: The WAF config of this policy. + returned: success + type: complex + sample: { + "access_rules": [], + "address_rate_limiting": { + "allowed_rate_per_address": 1, + "block_response_code": 503, + "is_enabled": false, + "max_delayed_count_per_address": 10 + }, + "captchas": [], + "device_fingerprint_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "DFC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "is_enabled": false, + "max_address_count": 20, + "max_address_count_expiration_in_seconds": 60 + }, + "good_bots": [ + { + "description": "Googlebot is the search bot software used by Google", + "is_enabled": false, + "key": "4a4c6e7b-4d89-4141-8555-ec3b22b90a73", + "name": "Googlebot " + }, + ], + "human_interaction_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "HIC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "interaction_threshold": 3, + "is_enabled": false, + "recording_period_in_seconds": 15, + "set_http_header": null + }, + "js_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "JSC-403", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "is_enabled": false, + "set_http_header": { + "name": "x-jsc-alerts", + "value": "{failed_amount}" + } + }, + "origin": "LBaaS", + "protection_rules": [ + { + "action": "OFF", + "description": "Cross-Site Scripting (XSS) Attempt: XSS Filters from IE", + "exclusions": [], + "key": "941340", + "labels": [ + "OWASP", + "OWASP-2017", + "CRS3", + "WASCTC", + "PCI", + "HTTP", + "A2", + "A2-2017", + "XSS", + "Cross-Site Scripting" + ], + "mod_security_rule_ids": [ + "941340" + ], + "name": "Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer" + }, + ], + "whitelists": []} + sample: [{ + "additional_domains": ["www.exampledomain1.com", "www.exampledomain2.com"], + "cname": "www-exampledomain-com.b.waas.oci.oraclecloud.net", + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "defined_tags": {"example_namespace": {"example_key": "example_value"}}, + "display_name": "ansible_test_waas_policy", + "domain": "www.example.com", + "freeform_tags": {"example_freeform_key": "example_freeform_value"}, + "id": "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx", + "lifecycle_state": "ACTIVE", + "origins": {"LBaaS": {"custom_headers": [], "http_port": 80, "https_port": 443, "uri": "1.2.3.4"}}, + "policy_config": {"certificate_id": null, "is_https_enabled": false, "is_https_forced": false}, + "time_created": "2019-03-22T13:02:55.563000+00:00", + "waf_config": { + "access_rules": [], + "address_rate_limiting": { + "allowed_rate_per_address": 1, + "block_response_code": 503, + "is_enabled": false, + "max_delayed_count_per_address": 10 + }, + "captchas": [], + "device_fingerprint_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "DFC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "is_enabled": false, + "max_address_count": 20, + "max_address_count_expiration_in_seconds": 60 + }, + "good_bots": [ + { + "description": "Googlebot is the search bot software used by Google.", + "is_enabled": false, + "key": "4a4c6e7b-4d89-4141-8555-ec3b22b90a73", + "name": "Googlebot " + }, + ], + "human_interaction_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "HIC", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "failure_threshold_expiration_in_seconds": 60, + "interaction_threshold": 3, + "is_enabled": false, + "recording_period_in_seconds": 15, + "set_http_header": null + }, + "js_challenge": { + "action": "DETECT", + "action_expiration_in_seconds": 60, + "challenge_settings": { + "block_action": "SHOW_ERROR_PAGE", + "block_error_page_code": "JSC-403", + "block_error_page_description": "Access blocked by website owner. Please contact support.", + "block_error_page_message": "Access to the website is blocked.", + "block_response_code": 403, + "captcha_footer": "Enter the letters and numbers as they are shown in image above.", + "captcha_header": "We have detected an increased number of attempts to access this website.", + "captcha_submit_label": "Yes, I am human.", + "captcha_title": "Are you human?" + }, + "failure_threshold": 10, + "is_enabled": false, + "set_http_header": { + "name": "x-jsc-alerts", + "value": "{failed_amount}" + } + }, + "origin": "LBaaS", + "protection_rules": [ + { + "action": "OFF", + "description": "Cross-Site Scripting (XSS) Attempt: XSS Filters from IE", + "exclusions": [], + "key": "941340", + "labels": [ + "OWASP", + "OWASP-2017", + "CRS3", + "WASCTC", + "PCI", + "HTTP", + "A2", + "A2-2017", + "XSS", + "Cross-Site Scripting" + ], + "mod_security_rule_ids": [ + "941340" + ], + "name": "Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer" + }, + ], + "whitelists": []} + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_waas_policies(waas_client, module): + compartment_id = module.params["compartment_id"] + optional_list_method_params = [ + "sort_by", + "sort_order", + "id", + "display_name", + "lifecycle_state", + "time_created_greater_than_or_equal_to", + "time_created_less_than", + ] + optional_kwargs = dict( + (param, module.params[param]) + for param in optional_list_method_params + if module.params.get(param) is not None + ) + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_waas_policy, waas_policy_id=waas_policy.id + ).data + for waas_policy in oci_utils.list_all_resources( + waas_client.list_waas_policies, + compartment_id=compartment_id, + **optional_kwargs + ) + ] + ) + + +def get_waas_policy(waas_client, module): + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_waas_policy, + waas_policy_id=module.params["waas_policy_id"], + ).data + ] + ) + + +def main(): + module_args = oci_utils.get_facts_module_arg_spec( + filter_by_display_name=False, + supports_sort=True, + sort_by_choices=["id", "displayName", "timeCreated"], + ) + module_args.update( + dict( + compartment_id=dict(type="str"), + waas_policy_id=dict(type="str"), + display_name=dict(type="list"), + id=dict(type="list"), + lifecycle_state=dict(type="list"), + time_created_greater_than_or_equal_to=dict(type="str"), + time_created_less_than=dict(type="str"), + ) + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[("compartment_id", "waas_policy_id")], + ) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + waas_client = oci_utils.create_service_client(module, WaasClient) + try: + if module.params["waas_policy_id"]: + result = get_waas_policy(waas_client, module) + elif module.params["compartment_id"]: + result = list_waas_policies(waas_client, module) + else: + module.fail_json( + msg="Specify a compartment_id to get all the waas policies in the compartment or a " + "waas_policy_id to retrieve a specific waas policy" + ) + except ServiceError as se: + module.fail_json(msg=se.message) + + module.exit_json(waas_policies=result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_recommendation_facts.py b/library/oci_waas_recommendation_facts.py new file mode 100644 index 0000000..e32183f --- /dev/null +++ b/library/oci_waas_recommendation_facts.py @@ -0,0 +1,175 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_recommendation_facts +short_description: Retrieve details about WAAS policy recommendations. +description: + - This module retrieves information of recommended Web Application Firewall protection rules for a WAAS policy. +version_added: "2.5" +options: + waas_policy_id: + description: The OCID of the WAAS policy. + type: str + required: true + recommended_action: + description: A filter that matches recommended protection rules based on the selected action. + If unspecified, rules with any action type are returned. + type: str + choices: + - DETECT + - BLOCK +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle ] +""" + +EXAMPLES = """ +- name: Get the recommendations for a waas policy + oci_waas_recommendation_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + +- name: Get the recommendations of specific action for a waas policy + oci_waas_recommendation_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + recommended_action: DETECT +""" + +RETURN = """ +waas_recommendations: + description: List of recommended Web Application Firewall protection rules for a WAAS policy. + returned: on success + type: complex + contains: + description: + description: The description of the recommended protection rule. + returned: success + type: str + sample: "Cross-Site Scripting (XSS) Attempt: XSS Filters from IE" + key: + description: The unique key for the recommended protection rule. + returned: success + type: str + sample: 941340 + labels: + description: The list of labels for the recommended protection rule. + returned: success + type: list + sample: [ + "OWASP", + "OWASP-2017", + "CRS3", + "WASCTC", + "PCI", + "HTTP", + "A2", + "A2-2017", + "XSS", + "Cross-Site Scripting" + ] + mod_security_rule_ids: + description: The list of the ModSecurity rule IDs associated with the protection rule. + returned: success + type: list + sample: ["941340"] + name: + description: The name of the recommended protection rule. + returned: success + type: str + sample: "Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer" + recommended_action: + description: The recommended action to apply to the protection rule. + returned: success + type: str + sample: BLOCK + sample: [{ + "description": "Cross-Site Scripting (XSS) Attempt: XSS Filters from IE", + "key": "941340", + "labels": [ + "OWASP", + "OWASP-2017", + "CRS3", + "WASCTC", + "PCI", + "HTTP", + "A2", + "A2-2017", + "XSS", + "Cross-Site Scripting" + ], + "mod_security_rule_ids": ["941340"], + "name": "Cross-Site Scripting (XSS) Attempt: XSS Filters from Internet Explorer", + "recommended_action": "BLOCK" + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_recommendations(waas_client, module): + optional_list_method_params = ["recommended_action"] + optional_kwargs = dict( + (param, module.params[param]) + for param in optional_list_method_params + if module.params.get(param) is not None + ) + return to_dict( + oci_utils.list_all_resources( + waas_client.list_recommendations, + waas_policy_id=module.params["waas_policy_id"], + **optional_kwargs + ) + ) + + +def main(): + module_args = oci_utils.get_facts_module_arg_spec(filter_by_display_name=False) + module_args.update( + dict( + waas_policy_id=dict(type="str", required=True), + recommended_action=dict(type="str", choices=["DETECT", "BLOCK"]), + ) + ) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=False) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + waas_client = oci_utils.create_service_client(module, WaasClient) + + try: + result = list_recommendations(waas_client, module) + except ServiceError as se: + module.fail_json(msg=se.message) + + module.exit_json(waas_recommendations=result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_work_request.py b/library/oci_waas_work_request.py new file mode 100644 index 0000000..f6b9b9a --- /dev/null +++ b/library/oci_waas_work_request.py @@ -0,0 +1,190 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_work_request +short_description: Manage WAAS policy work requests in OCI +description: + - This module allows the user to cancel a WAAS policy work request in OCI. +version_added: "2.5" +options: + work_request_id: + description: The OCID of the work request. Required to retrieve a specific work request. + type: str + required: true + state: + description: Cancel a WAAS work request with I(state=cancelled). + default: cancelled + choices: ['cancelled'] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_wait_options ] +""" + +EXAMPLES = """ +- name: Cancel a waas work request + oci_waas_work_request: + work_request_id: "ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx" + state: cancelled + +- name: Cancel a waas work request without explicitly stating the state as it is default + oci_waas_work_request: + work_request_id: "ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx" +""" + +RETURN = """ +waas_work_request: + description: Information about the WAAS work request. + returned: on success + type: complex + contains: + compartment_id: + description: The OCID of the compartment that contains the work request. + returned: success + type: str + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + errors: + description: The list of errors that occurred while fulfilling the work request. + returned: success + type: list + sample: [] + id: + description: The OCID of the work request. + returned: success + type: str + sample: ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx + logs: + description: The list of log entries from the work request workflow. + returned: success + type: list + sample: [] + operation_type: + description: A description of the operation requested by the work request. + returned: success + type: str + sample: "UPDATE_WAAS_POLICY" + percent_complete: + description: The percentage of work completed by the work request. + returned: success + type: int + sample: 0 + resources: + description: The resources being used to complete the work request operation. + returned: success + type: str + sample: [] + status: + description: The current status of the work request. + returned: success + type: str + sample: "CANCELLED" + time_accepted: + description: The date and time the work request was created, in the format defined by RFC3339. + returned: success + type: str + sample: 2019-03-22T13:02:55.563000+00:00 + time_finished: + description: The date and time the work request was fulfilled or terminated, expressed in RFC 3339 + timestamp format. + returned: success + type: str + sample: null + time_started: + description: The date and time the work request moved from the ACCEPTED state to the IN_PROGRESS state, + expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: null + sample: { + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "errors": [], + "logs": [], + "operation_type": "UPDATE_WAAS_POLICY", + "percent_complete": 0, + "resources": [], + "status": "CANCELLED", + "time_accepted": "2019-03-22T13:02:55.563000+00:00", + "time_finished": null, + "time_started": null, + } +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + + +try: + import oci + from oci.util import to_dict + from oci.exceptions import ServiceError + from oci.waas.waas_client import WaasClient + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + + +def cancel_work_request(waas_client, module): + result = dict(changed=False) + oci_utils.call_with_backoff( + waas_client.cancel_work_request, + work_request_id=module.params["work_request_id"], + ) + result["changed"] = True + work_request_response = oci_utils.call_with_backoff( + waas_client.get_work_request, work_request_id=module.params["work_request_id"] + ) + if not module.params.get("wait"): + result["waas_work_request"] = to_dict(work_request_response.data) + return result + work_request_response = oci.wait_until( + waas_client, + work_request_response, + evaluate_response=lambda r: r.data.status in oci_utils.CANCELLED_STATES, + max_wait_seconds=module.params.get( + "wait_timeout", oci_utils.MAX_WAIT_TIMEOUT_IN_SECONDS + ), + ) + result["waas_work_request"] = to_dict(work_request_response.data) + return result + + +def main(): + module_args = oci_utils.get_common_arg_spec(supports_wait=True) + module_args.update( + dict( + work_request_id=dict(type="str", required=True), + state=dict(type="str", default="cancelled", choices=["cancelled"]), + ) + ) + + module = AnsibleModule(argument_spec=module_args, supports_check_mode=False) + + waas_client = oci_utils.create_service_client(module, WaasClient) + + try: + result = cancel_work_request(waas_client, module) + except ServiceError as se: + module.fail_json( + msg="Cancelling work request failed with error: {0}".format(se.message) + ) + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/library/oci_waas_work_request_facts.py b/library/oci_waas_work_request_facts.py new file mode 100644 index 0000000..e62749d --- /dev/null +++ b/library/oci_waas_work_request_facts.py @@ -0,0 +1,285 @@ +#!/usr/bin/python +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: oci_waas_work_request_facts +short_description: Retrieve details about WAAS policy work requests. +description: + - This module retrieves information of a specific work request or lists all the work requests in the given WAAS + policy and compartment. +version_added: "2.5" +options: + waas_policy_id: + description: The OCID of the WAAS policy. + type: str + compartment_id: + description: The OCID of the compartment. + type: str + work_request_id: + description: The OCID of the work request. Required to retrieve a specific work request. + type: str + sort_by: + description: The value by which work requests are sorted in a paginated 'List' call. + If unspecified, defaults to timeAccepted. + type: str + choices: ["id", "status", "timeAccepted", "timeStarted", "timeFinished", "operationType"] +author: "Manoj Meda (@manojmeda)" +extends_documentation_fragment: [ oracle, oracle_sort_order_option ] +""" + +EXAMPLES = """ +- name: Get all the work requests for a waas policy in a compartment + oci_waas_work_request_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + +- name: Get all the work requests for a waas policy in a compartment sorted by timeFinished + oci_waas_work_request_facts: + waas_policy_id: ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx + compartment_id: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + sort_by: timeFinished + +- name: Get a specific waas work request using its OCID + oci_waas_work_request_facts: + work_request_id: ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx +""" + +RETURN = """ +waas_work_requests: + description: List of work requests + returned: on success + type: complex + contains: + compartment_id: + description: The OCID of the compartment that contains the work request. + returned: success + type: str + sample: ocid1.compartment.oc1..xxxxxEXAMPLExxxxx + errors: + description: The list of errors that occurred while fulfilling the work request. + returned: success + type: list + sample: [] + id: + description: The OCID of the work request. + returned: success + type: str + sample: ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx + logs: + description: The list of log entries from the work request workflow. + returned: success + type: list + sample: [ + { + "message": "Work request complete", + "timestamp": "2019-04-10T19:31:57.364000+00:00" + }, + { + "message": "PersistWaasOp: start (100% of request completed)", + "timestamp": "2019-04-10T19:31:57.360000+00:00" + }, + { + "message": "Starting Work Request", + "timestamp": "2019-04-10T19:31:57.261000+00:00" + } + ] + operation_type: + description: A description of the operation requested by the work request. + returned: success + type: str + sample: "CREATE_WAAS_POLICY" + percent_complete: + description: The percentage of work completed by the work request. + returned: success + type: int + sample: 50 + resources: + description: The resources being used to complete the work request operation. + returned: success + type: str + sample: [ + { + "action_type": "CREATED", + "entity_type": "waas", + "entity_uri": "/20181116/waasPolicies/ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx", + "identifier": "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx" + } + ] + status: + description: The current status of the work request. + returned: success + type: str + sample: "IN_PROGRESS" + time_accepted: + description: The date and time the work request was created, in the format defined by RFC3339. + returned: success + type: str + sample: 2019-03-22T13:02:55.563000+00:00 + time_finished: + description: The date and time the work request was fulfilled or terminated, expressed in RFC 3339 + timestamp format. + returned: success + type: str + sample: 2019-03-22T13:02:59.563000+00:00 + time_started: + description: The date and time the work request moved from the ACCEPTED state to the IN_PROGRESS state, + expressed in RFC 3339 timestamp format. + returned: success + type: str + sample: 2019-03-22T13:02:56.563000+00:00 + sample: [{ + "compartment_id": "ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + "errors": [], + "id": "ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx", + "logs": [ + { + "message": "addWhitelistOp: start", + "timestamp": "2019-04-10T18:46:05.663000+00:00" + }, + { + "message": "addWhitelistOp: finished (45% of request completed)", + "timestamp": "2019-04-10T18:46:05.663000+00:00" + }, + { + "message": "updateProtectionSettingsOp: start", + "timestamp": "2019-04-10T18:46:05.403000+00:00" + }, + ], + "operation_type": "CREATE_WAAS_POLICY", + "percent_complete": 45, + "resources": [ + { + "action_type": "CREATED", + "entity_type": "waas", + "entity_uri": "/20181116/waasPolicies/ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx", + "identifier": "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx" + } + ], + "status": "IN_PROGRESS", + "time_accepted": "2019-04-10T18:45:45.044000+00:00", + "time_finished": null, + "time_started": "2019-04-10T18:45:49+00:00" + }] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.oracle import oci_utils + + +try: + from oci.waas.waas_client import WaasClient + from oci.util import to_dict + from oci.exceptions import ServiceError + + HAS_OCI_PY_SDK = True + +except ImportError: + HAS_OCI_PY_SDK = False + + +def list_work_requests(waas_client, module): + if not ( + module.params.get("waas_policy_id") and module.params.get("compartment_id") + ): + module.fail_json( + msg="waas_policy_id and compartment_id are required to list work requests." + ) + optional_list_method_params = ["sort_by", "sort_order"] + optional_kwargs = dict( + (param, module.params[param]) + for param in optional_list_method_params + if module.params.get(param) is not None + ) + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_work_request, work_request_id=work_request.id + ).data + for work_request in oci_utils.list_all_resources( + waas_client.list_work_requests, + waas_policy_id=module.params["waas_policy_id"], + compartment_id=module.params["compartment_id"], + **optional_kwargs + ) + ] + ) + + +def get_work_request(waas_client, module): + return to_dict( + [ + oci_utils.call_with_backoff( + waas_client.get_work_request, + work_request_id=module.params["work_request_id"], + ).data + ] + ) + + +def main(): + module_args = oci_utils.get_facts_module_arg_spec( + filter_by_display_name=False, + supports_sort=True, + sort_by_choices=[ + "id", + "status", + "timeAccepted", + "timeStarted", + "timeFinished", + "operationType", + ], + ) + module_args.update( + dict( + work_request_id=dict(type="str"), + compartment_id=dict(type="str"), + waas_policy_id=dict(type="str"), + ) + ) + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=False, + mutually_exclusive=[ + ["work_request_id", "compartment_id"], + ["work_request_id", "waas_policy_id"], + ], + ) + + if not HAS_OCI_PY_SDK: + module.fail_json(msg="oci python sdk required for this module.") + + waas_client = oci_utils.create_service_client(module, WaasClient) + + try: + if module.params["work_request_id"]: + result = get_work_request(waas_client, module) + elif module.params["waas_policy_id"] and module.params["compartment_id"]: + result = list_work_requests(waas_client, module) + else: + module.fail_json( + msg="Specify waas_policy_id and compartment_id to get all the work requests for a waas policy in the" + "compartment or work_request_id to retrieve a specific work request." + ) + except ServiceError as se: + module.fail_json(msg=se.message) + + module.exit_json(waas_work_requests=result) + + +if __name__ == "__main__": + main() diff --git a/module_docs_fragments/oracle_sort_options.py b/module_docs_fragments/oracle_sort_options.py new file mode 100644 index 0000000..ea5f027 --- /dev/null +++ b/module_docs_fragments/oracle_sort_options.py @@ -0,0 +1,22 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + + +class ModuleDocFragment(object): + DOCUMENTATION = """ + options: + sort_by: + description: The field to sort the results by. Default order for I(TIMECREATED) is descending. + Default order for I(DISPLAYNAME) is ascending. The DISPLAYNAME sort order is case sensitive. + required: false + type: str + choices: ['TIMECREATED', 'DISPLAYNAME'] + sort_order: + description: The order in which to sort the results. + required: false + type: str + choices: ['ASC', 'DESC'] + """ diff --git a/module_docs_fragments/oracle_sort_order_option.py b/module_docs_fragments/oracle_sort_order_option.py new file mode 100644 index 0000000..12db69e --- /dev/null +++ b/module_docs_fragments/oracle_sort_order_option.py @@ -0,0 +1,16 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + + +class ModuleDocFragment(object): + DOCUMENTATION = """ + options: + sort_order: + description: The order in which to sort the results. + required: false + type: str + choices: ['ASC', 'DESC'] + """ diff --git a/module_utils/oracle/oci_compute_utils.py b/module_utils/oracle/oci_compute_utils.py index 8ca8604..68e0486 100644 --- a/module_utils/oracle/oci_compute_utils.py +++ b/module_utils/oracle/oci_compute_utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -8,6 +8,7 @@ try: from oci.util import to_dict + from oci.exceptions import ServiceError HAS_OCI_PY_SDK = True except ImportError: @@ -55,3 +56,33 @@ def get_boot_volume_attachment(compute_client, instance): if boot_volume_attachments: return boot_volume_attachments[0] return None + + +def get_primary_ips(compute_client, network_client, instance): + primary_public_ip = None + primary_private_ip = None + + vnic_attachments = oci_utils.list_all_resources( + compute_client.list_vnic_attachments, + compartment_id=instance["compartment_id"], + instance_id=instance["id"], + ) + + if vnic_attachments: + for vnic_attachment in vnic_attachments: + if vnic_attachment.lifecycle_state == "ATTACHED": + try: + vnic = network_client.get_vnic(vnic_attachment.vnic_id).data + if vnic.is_primary: + if vnic.public_ip: + primary_public_ip = vnic.public_ip + if vnic.private_ip: + primary_private_ip = vnic.private_ip + except ServiceError as ex: + if ex.status == 404: + get_logger().debug( + "Either VNIC with ID %s does not exist or you are not authorized to access it.", + vnic_attachment.vnic_id, + ) + + return primary_public_ip, primary_private_ip diff --git a/module_utils/oracle/oci_utils.py b/module_utils/oracle/oci_utils.py index 3565b9c..95c30a7 100644 --- a/module_utils/oracle/oci_utils.py +++ b/module_utils/oracle/oci_utils.py @@ -41,7 +41,7 @@ from ansible.module_utils.basic import _load_params from ansible.module_utils._text import to_bytes -__version__ = "1.7.0" +__version__ = "1.8.0" MAX_WAIT_TIMEOUT_IN_SECONDS = 1200 @@ -70,6 +70,12 @@ "PENDING_PROVIDER", ] +CANCELLED_STATES = ["CANCELLED"] + +WORK_REQUEST_COMPLETED_STATES = ["SUCCEEDED", "SUCCESS", "FAILED"] +WORK_REQUEST_SUCCESS_STATES = ["SUCCEEDED", "SUCCESS"] +WORK_REQUEST_FAILED_STATES = ["FAILED"] + # If a resource is in one of these states, it would be considered deleted DEFAULT_TERMINATED_STATES = ["TERMINATED", "DETACHED", "DELETED"] @@ -86,50 +92,65 @@ def get_common_arg_spec(supports_create=False, supports_wait=False): # can check for absence of OCI Python SDK and fail with an appropriate message. Introducing an OCI dependency in # this method would break that error handling logic. common_args = dict( - config_file_location=dict(type="str", required=False), - config_profile_name=dict(type="str", required=False), - api_user=dict(type="str", required=False), - api_user_fingerprint=dict(type="str", required=False, no_log=True), - api_user_key_file=dict(type="str", required=False), - api_user_key_pass_phrase=dict(type="str", required=False, no_log=True), + config_file_location=dict(type="str"), + config_profile_name=dict(type="str"), + api_user=dict(type="str"), + api_user_fingerprint=dict(type="str", no_log=True), + api_user_key_file=dict(type="str"), + api_user_key_pass_phrase=dict(type="str", no_log=True), auth_type=dict( - type="str", - required=False, - choices=["api_key", "instance_principal"], - default="api_key", + type="str", choices=["api_key", "instance_principal"], default="api_key" ), - tenancy=dict(type="str", required=False), - region=dict(type="str", required=False), + tenancy=dict(type="str"), + region=dict(type="str"), ) if supports_create: common_args.update( - key_by=dict(type="list", required=False), - force_create=dict(type="bool", required=False, default=False), + key_by=dict(type="list"), force_create=dict(type="bool", default=False) ) if supports_wait: common_args.update( - wait=dict(type="bool", required=False, default=True), - wait_timeout=dict( - type="int", required=False, default=MAX_WAIT_TIMEOUT_IN_SECONDS - ), - wait_until=dict(type="str", required=False), + wait=dict(type="bool", default=True), + wait_timeout=dict(type="int", default=MAX_WAIT_TIMEOUT_IN_SECONDS), + wait_until=dict(type="str"), ) return common_args -def get_facts_module_arg_spec(filter_by_name=False): +def get_facts_module_arg_spec( + filter_by_name=False, + filter_by_display_name=True, + supports_sort=False, + supports_sort_by=True, + sort_by_choices=None, + supports_sort_order=True, + sort_order_choices=None, +): # Note: This method is used by most OCI ansible fact modules during initialization. When making changes to this # method, ensure that no `oci` python sdk dependencies are introduced in this method. This ensures that the modules # can check for absence of OCI Python SDK and fail with an appropriate message. Introducing an OCI dependency in # this method would break that error handling logic. facts_module_arg_spec = get_common_arg_spec() if filter_by_name: - facts_module_arg_spec.update(name=dict(type="str", required=False)) - else: - facts_module_arg_spec.update(display_name=dict(type="str", required=False)) + facts_module_arg_spec.update(name=dict(type="str")) + elif filter_by_display_name: + facts_module_arg_spec.update(display_name=dict(type="str")) + if supports_sort: + if supports_sort_by: + if not sort_by_choices: + sort_by_choices = ["TIMECREATED", "DISPLAYNAME"] + facts_module_arg_spec.update( + sort_by=dict(type="str", choices=sort_by_choices) + ) + if supports_sort_order: + if not sort_order_choices: + sort_order_choices = ["ASC", "DESC"] + facts_module_arg_spec.update( + sort_order=dict(type="str", choices=sort_order_choices) + ) return facts_module_arg_spec @@ -471,7 +492,7 @@ def setup_logging( log_level_str = os.getenv(env_log_level, default_level) log_level = logging.getLevelName(log_level_str) - log_file_path = os.path.join(tempfile.gettempdir(), "oci_ansible_module.log") + log_file_path = os.path.join(log_path, "oci_ansible_module.log") logging.basicConfig(filename=log_file_path, filemode="a", level=log_level) return logging @@ -511,6 +532,7 @@ def check_and_update_resource( sub_attributes_of_update_model=None, wait_applicable=True, states=None, + required_update_attributes=[], ): """ @@ -534,12 +556,14 @@ def check_and_update_resource( e.g. [module.params['wait_until'], "FAULTY"] :param sub_attributes_of_update_model: Dictionary of non-primitive sub-attributes of update model. for example, {'services': [ServiceIdRequestDetails()]} as in UpdateServiceGatewayDetails. + :param required_update_attributes: Attributes in update model that must be passed, even if their value already matches + the value on the resource. :return: Returns a dictionary containing the "changed" status and the resource. """ try: result = dict(changed=False) attributes_to_update, resource = get_attr_to_update( - get_fn, kwargs_get, module, update_attributes + get_fn, kwargs_get, module, update_attributes, required_update_attributes ) if attributes_to_update: @@ -638,7 +662,9 @@ def are_lists_equal(s, t): return not t -def get_attr_to_update(get_fn, kwargs_get, module, update_attributes): +def get_attr_to_update( + get_fn, kwargs_get, module, update_attributes, required_update_attributes=[] +): try: resource = call_with_backoff(get_fn, **kwargs_get).data except ServiceError as ex: @@ -656,7 +682,7 @@ def get_attr_to_update(get_fn, kwargs_get, module, update_attributes): unequal_attr = type(resources_attr_value) != list and to_dict( resources_attr_value ) != to_dict(user_provided_attr_value) - if unequal_list_attr or unequal_attr: + if unequal_list_attr or unequal_attr or attr in required_update_attributes: # only update if the user has explicitly provided a value for this attribute # otherwise, no update is necessary because the user hasn't expressed a particular # value for that attribute @@ -723,10 +749,13 @@ def check_and_create_resource( model, existing_resources=None, exclude_attributes=None, + exclude_attributes_even_when_user_provides_value=None, dead_states=None, default_attribute_values=None, supports_sort_by_time_created=True, create_model_attr_to_get_model_mapping=None, + get_resource_from_summary_fn=None, + get_resource_from_summary_fn_kwargs=None, ): """ This function checks whether there is a resource with same attributes as specified in the module options. If not, @@ -744,6 +773,14 @@ def check_and_create_resource( :param dead_states: List of states which can't transition to any of the usable states of the resource. This deafults to ["TERMINATING", "TERMINATED", "FAULTY", "FAILED", "DELETING", "DELETED", "UNKNOWN_ENUM_VALUE"] :param default_attribute_values: A dictionary containing default values for attributes. + :param supports_sort_by_time_created: Whether the list function supports sort_by. + :param create_model_attr_to_get_model_mapping: Mapping between attribute names in create and get model. + For some resources, the attribute names in the create model and + get model are different. In that cases, idempotency fails. For ex: + api keys. + :param get_resource_from_summary_dict_fn: Function to get the full resource from a summary resource dict. First + parameter of this function should be the summary resource. + :param get_resource_from_summary_dict_fn_kwargs: kwargs to pass to get_resource_from_summary_dict_fn :return: A dictionary containing the resource & the "changed" status. e.g. {"vcn":{x:y}, "changed":True} """ @@ -774,10 +811,27 @@ def check_and_create_resource( except ServiceError as ex: module.fail_json(msg=ex.message) + try: + if get_resource_from_summary_fn: + get_resource_from_summary_fn_kwargs = ( + get_resource_from_summary_fn_kwargs or {} + ) + existing_resources = [ + get_resource_from_summary_fn( + existing_resource, **get_resource_from_summary_fn_kwargs + ) + for existing_resource in existing_resources + ] + except Exception as ex: + module.fail_json(msg=str(ex)) + result = dict() attributes_to_consider = _get_attributes_to_consider( - exclude_attributes, model, module + exclude_attributes, + model, + module, + exclude_attributes_even_when_user_provides_value=exclude_attributes_even_when_user_provides_value, ) if "defined_tags" not in default_attribute_values: default_attribute_values["defined_tags"] = {} @@ -816,7 +870,12 @@ def check_and_create_resource( return result -def _get_attributes_to_consider(exclude_attributes, model, module): +def _get_attributes_to_consider( + exclude_attributes, + model, + module, + exclude_attributes_even_when_user_provides_value=None, +): """ Determine the attributes to detect if an existing resource already matches the requested resource state :param exclude_attributes: Attributes to not consider for matching @@ -837,6 +896,10 @@ def _get_attributes_to_consider(exclude_attributes, model, module): # Temporarily removing node_count as the exisiting resource does not reflect it if "node_count" in attributes_to_consider: attributes_to_consider.remove("node_count") + if exclude_attributes_even_when_user_provides_value: + for exclude_attr in exclude_attributes_even_when_user_provides_value: + if exclude_attr in attributes_to_consider: + attributes_to_consider.remove(exclude_attr) _debug("attributes to consider: {0}".format(attributes_to_consider)) return attributes_to_consider @@ -898,6 +961,10 @@ def has_user_provided_value_for_option(module, option): return False +def get_work_request_id(response): + return response.headers.get("opc-work-request-id") + + def create_resource(resource_type, create_fn, kwargs_create, module): """ Create an OCI resource @@ -1344,6 +1411,52 @@ def create_and_wait( module.fail_json(msg=ex.message) +def create_and_wait_on_work_request( + resource_type, + create_fn, + kwargs_create, + module, + client, + get_work_request_id_fn=get_work_request_id, + get_resource_from_work_request_response_fn=None, + wait_applicable=True, +): + """ + A utility function to create or update a resource and wait for the resource to get into the state as specified in + the module options. + :param resource_type: Type of the resource to be created. e.g. "vcn" + :param function: Function in the SDK to create or update the resource. + :param kwargs_function: Dictionary containing arguments to be used to call the create or update function + :param module: Instance of AnsibleModule. + :param wait_applicable: Specifies if wait for create is applicable for this resource + :param client: OCI service client instance to call the service periodically to retrieve data. + e.g. VirtualNetworkClient() + :param get_work_request_id_fn: Function to get the work request ocid from the response. Applicable only when + `process_work_request` is True. + :param get_resource_from_work_request_response_fn: Function to get the resource from the work request response. + :return: A dictionary containing the resource & the "changed" status. e.g. {"vcn":{x:y}, "changed":True} + """ + try: + result = dict(changed=False) + response = call_with_backoff(create_fn, **kwargs_create) + result["changed"] = True + result[resource_type] = to_dict(response.data) + work_request_id = get_work_request_id_fn(response) + _debug("Work request id: {0}".format(work_request_id)) + result[resource_type] = wait_for_work_request( + client, + module, + wait_applicable, + work_request_id, + get_resource_from_work_request_response_fn=get_resource_from_work_request_response_fn, + ) + return result + except MaximumWaitTimeExceeded as mwteex: + module.fail_json(msg=str(mwteex)) + except ServiceError as se: + module.fail_json(msg=se.message) + + def update_and_wait( resource_type, client, @@ -1438,6 +1551,66 @@ def create_or_update_resource_and_wait( return result +def _is_work_request_success(work_request_response, status_attr=None): + if status_attr: + return ( + getattr(work_request_response.data, status_attr, None) + in WORK_REQUEST_SUCCESS_STATES + ) + if hasattr(work_request_response.data, "lifecycle_state"): + return work_request_response.data.lifecycle_state in WORK_REQUEST_SUCCESS_STATES + if hasattr(work_request_response, "status"): + return work_request_response.data.status in WORK_REQUEST_SUCCESS_STATES + return False + + +def get_work_request_errors(work_request_response, errors_attr=None): + if errors_attr: + return getattr(work_request_response.data, errors_attr, None) + if hasattr(work_request_response.data, "errors"): + return work_request_response.data.errors + if hasattr(work_request_response.data, "error_details"): + return work_request_response.data.error_details + return None + + +def wait_for_work_request( + client, + module, + wait_applicable, + work_request_id, + errors_attr=None, + states=None, + get_resource_from_work_request_response_fn=None, +): + if not (wait_applicable and module.params.get("wait")): + return None + if not work_request_id: + module.fail_json(msg="Unable to get the work request for the operation.") + work_request_response = call_with_backoff( + client.get_work_request, work_request_id=work_request_id + ) + states = states or module.params.get("wait_until") or WORK_REQUEST_COMPLETED_STATES + work_request_response = oci.wait_until( + client, + work_request_response, + evaluate_response=lambda response: response.data.status in states, + max_wait_seconds=module.params.get("wait_timeout", MAX_WAIT_TIMEOUT_IN_SECONDS), + ) + if not _is_work_request_success(work_request_response): + module.fail_json( + "Work request {0} failed with errors: {1}".format( + work_request_id, + get_work_request_errors(work_request_response, errors_attr=errors_attr), + ) + ) + if not get_resource_from_work_request_response_fn: + return None + return get_resource_from_work_request_response_fn( + work_request_response=work_request_response, module=module, client=client + ) + + def wait_for_resource_lifecycle_state( client, module, @@ -1480,6 +1653,9 @@ def wait_for_resource_lifecycle_state( kwargs_get ) ) + if get_param: + kwargs_get[get_param] = resource["id"] + response_get = call_with_backoff(get_fn, **kwargs_get) else: _debug( diff --git a/module_utils/oracle/oci_waas_utils.py b/module_utils/oracle/oci_waas_utils.py new file mode 100644 index 0000000..2bbfa48 --- /dev/null +++ b/module_utils/oracle/oci_waas_utils.py @@ -0,0 +1,657 @@ +# Copyright (c) 2019 Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible.module_utils.oracle import oci_utils + +try: + from oci.util import to_dict + from oci.waas.models import ( + CreateWaasPolicyDetails, + Origin, + Header, + PolicyConfig, + WafConfigDetails, + WafConfig, + AccessRule, + AccessRuleCriteria, + AddressRateLimiting, + Captcha, + DeviceFingerprintChallenge, + GoodBot, + BlockChallengeSettings, + HumanInteractionChallenge, + JsChallenge, + ProtectionRule, + ProtectionRuleExclusion, + ProtectionSettings, + Whitelist, + ThreatFeed, + ) + + HAS_OCI_PY_SDK = True +except ImportError: + HAS_OCI_PY_SDK = False + + +logger = oci_utils.get_logger("oci_waas_utils") + + +def get_waas_origins(module): + if not module.params.get("origins"): + return None + origins = dict() + for origin_name in module.params["origins"]: + origin_dict = module.params["origins"][origin_name] + origin = get_model_from_dict( + Origin, origin_dict, ["http_port", "https_port", "uri"] + ) + if origin_dict.get("custom_headers"): + origin.custom_headers = [] + for header_dict in origin_dict["custom_headers"]: + header = get_model_from_dict(Header, header_dict, ["name", "value"]) + origin.custom_headers.append(header) + + origins[origin_name] = origin + return origins + + +def get_waas_policy_config(module): + if not module.params.get("policy_config"): + return None + return get_model_from_dict( + PolicyConfig, + module.params.get("policy_config"), + ["certificate_id", "is_https_enabled", "is_https_forced"], + ) + + +def get_waf_config_access_rules(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("access_rules"): + return None + waf_config_dict_access_rules = waf_config_dict["access_rules"] + access_rules = [] + for access_rule_dict in waf_config_dict_access_rules: + access_rule = get_model_from_dict( + AccessRule, + access_rule_dict, + [ + "name", + "action", + "block_action", + "block_response_code", + "block_error_page_message", + "block_error_page_code", + "block_error_page_description", + ], + ) + if "criteria" in access_rule_dict and access_rule_dict["criteria"]: + criteria = [] + for access_rule_criteria_dict in access_rule_dict["criteria"]: + access_rule_criteria = get_model_from_dict( + AccessRuleCriteria, + access_rule_criteria_dict, + ["condition", "value"], + ) + criteria.append(access_rule_criteria) + setattr(access_rule, "criteria", criteria) + access_rules.append(access_rule) + return access_rules + + +def get_waf_config_address_rate_limiting(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("address_rate_limiting"): + return None + return get_model_from_dict( + AddressRateLimiting, + waf_config_dict["address_rate_limiting"], + [ + "allowed_rate_per_address", + "block_response_code", + "is_enabled", + "max_delayed_count_per_address", + ], + ) + + +def get_waf_config_captchas(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("captchas"): + return None + waf_config_dict_captchas = waf_config_dict["captchas"] + captchas = [] + for captcha_dict in waf_config_dict_captchas: + captcha = get_model_from_dict( + Captcha, + captcha_dict, + [ + "url", + "session_expiration_in_seconds", + "title", + "header_text", + "footer_text", + "failure_message", + "submit_label", + ], + ) + captchas.append(captcha) + return captchas + + +def get_waf_config_device_fingerprint_challenge(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("device_fingerprint_challenge"): + return None + device_fingerprint_challenge_dict = waf_config_dict["device_fingerprint_challenge"] + device_fingerprint_challenge = get_model_from_dict( + DeviceFingerprintChallenge, + device_fingerprint_challenge_dict, + [ + "is_enabled", + "action", + "failure_threshold", + "action_expiration_in_seconds", + "failure_threshold_expiration_in_seconds", + "max_address_count", + "max_address_count_expiration_in_seconds", + ], + ) + if ( + "challenge_settings" in device_fingerprint_challenge_dict + and device_fingerprint_challenge_dict["challenge_settings"] + ): + challenge_settings_dict = device_fingerprint_challenge_dict[ + "challenge_settings" + ] + challenge_settings = get_model_from_dict( + BlockChallengeSettings, + challenge_settings_dict, + [ + "block_action", + "block_response_code", + "block_error_page_message", + "block_error_page_description", + "block_error_page_code", + "captcha_title", + "captcha_header", + "captcha_footer", + "captcha_submit_label", + ], + ) + setattr(device_fingerprint_challenge, "challenge_settings", challenge_settings) + return device_fingerprint_challenge + + +def get_waf_config_good_bots(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("good_bots"): + return None + waf_config_dict_good_bots = waf_config_dict["good_bots"] + good_bots = [] + for good_bot_dict in waf_config_dict_good_bots: + good_bot = get_model_from_dict( + GoodBot, good_bot_dict, ["description", "is_enabled", "key", "name"] + ) + good_bots.append(good_bot) + return good_bots + + +def get_waf_config_human_interaction_challenge(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("human_interaction_challenge"): + return None + human_interaction_challenge_dict = waf_config_dict["human_interaction_challenge"] + human_interaction_challenge = get_model_from_dict( + HumanInteractionChallenge, + human_interaction_challenge_dict, + [ + "is_enabled", + "action", + "failure_threshold", + "action_expiration_in_seconds", + "failure_threshold_expiration_in_seconds", + "interaction_threshold", + "recording_period_in_seconds", + ], + ) + if ( + "set_http_header" in human_interaction_challenge_dict + and human_interaction_challenge_dict["set_http_header"] + ): + set_http_header_dict = human_interaction_challenge_dict["set_http_header"] + set_http_header = get_model_from_dict( + Header, set_http_header_dict, ["name", "value"] + ) + setattr(human_interaction_challenge, "set_http_header", set_http_header) + if ( + "challenge_settings" in human_interaction_challenge_dict + and human_interaction_challenge_dict["challenge_settings"] + ): + challenge_settings_dict = human_interaction_challenge_dict["challenge_settings"] + challenge_settings = get_model_from_dict( + BlockChallengeSettings, + challenge_settings_dict, + [ + "block_action", + "block_response_code", + "block_error_page_message", + "block_error_page_description", + "block_error_page_code", + "captcha_title", + "captcha_header", + "captcha_footer", + "captcha_submit_label", + ], + ) + setattr(human_interaction_challenge, "challenge_settings", challenge_settings) + return human_interaction_challenge + + +def get_waf_config_js_challenge(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("js_challenge"): + return None + js_challenge_dict = waf_config_dict["js_challenge"] + js_challenge = get_model_from_dict( + JsChallenge, + js_challenge_dict, + ["is_enabled", "action", "failure_threshold", "action_expiration_in_seconds"], + ) + if "set_http_header" in js_challenge_dict and js_challenge_dict["set_http_header"]: + set_http_header_dict = js_challenge_dict["set_http_header"] + set_http_header = get_model_from_dict( + Header, set_http_header_dict, ["name", "value"] + ) + setattr(js_challenge, "set_http_header", set_http_header) + if ( + "challenge_settings" in js_challenge_dict + and js_challenge_dict["challenge_settings"] + ): + challenge_settings_dict = js_challenge_dict["challenge_settings"] + challenge_settings = get_model_from_dict( + BlockChallengeSettings, + challenge_settings_dict, + [ + "block_action", + "block_response_code", + "block_error_page_message", + "block_error_page_description", + "block_error_page_code", + "captcha_title", + "captcha_header", + "captcha_footer", + "captcha_submit_label", + ], + ) + setattr(js_challenge, "challenge_settings", challenge_settings) + return js_challenge + + +def get_waf_config_origin(waf_config_dict): + if not waf_config_dict: + return None + return waf_config_dict.get("origin") + + +def get_waf_config_protection_rules(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("protection_rules"): + return None + waf_config_dict_protection_rules = waf_config_dict["protection_rules"] + protection_rules = [] + for protection_rule_dict in waf_config_dict_protection_rules: + protection_rule = get_model_from_dict( + ProtectionRule, + protection_rule_dict, + ["key", "mod_security_rule_ids", "name", "description", "action", "labels"], + ) + if "exclusions" in protection_rule_dict: + exclusions = [] + for exclusion_dict in protection_rule_dict["exclusions"]: + exclusion = get_model_from_dict( + ProtectionRuleExclusion, exclusion_dict, ["target", "exclusions"] + ) + exclusions.append(exclusion) + setattr(protection_rule, "exclusions", exclusions) + protection_rules.append(protection_rule) + return protection_rules + + +def get_waf_config_protection_settings(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("protection_settings"): + return None + protection_settings_dict = waf_config_dict["protection_settings"] + protection_settings = get_model_from_dict( + ProtectionSettings, + protection_settings_dict, + [ + "block_action", + "block_response_code", + "block_error_page_message", + "block_error_page_code", + "block_error_page_description", + "max_argument_count", + "max_name_length_per_argument", + "max_total_name_length_of_arguments", + "recommendations_period_in_days", + "is_response_inspected", + "max_response_size_in_ki_b", + "allowed_http_methods", + "media_types", + ], + ) + return protection_settings + + +def get_waf_config_whitelists(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("whitelists"): + return None + waf_config_dict_whitelists = waf_config_dict["whitelists"] + whitelists = [] + for whitelist_dict in waf_config_dict_whitelists: + whitelist = get_model_from_dict( + Whitelist, whitelist_dict, ["addresses", "name"] + ) + whitelists.append(whitelist) + return whitelists + + +def get_waf_config_threat_feeds(waf_config_dict): + if not waf_config_dict: + return None + if not waf_config_dict.get("threat_feeds"): + return None + waf_config_dict_threat_feeds = waf_config_dict["threat_feeds"] + threat_feeds = [] + for threat_feed_dict in waf_config_dict_threat_feeds: + threat_feed = get_model_from_dict( + ThreatFeed, threat_feed_dict, ["key", "name", "action", "description"] + ) + threat_feeds.append(threat_feed) + return threat_feeds + + +def get_waf_config(module): + if not module.params.get("waf_config"): + return None + waf_config_details = WafConfigDetails() + setattr( + waf_config_details, + "access_rules", + get_waf_config_access_rules(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "address_rate_limiting", + get_waf_config_address_rate_limiting(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "captchas", + get_waf_config_captchas(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "device_fingerprint_challenge", + get_waf_config_device_fingerprint_challenge(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "human_interaction_challenge", + get_waf_config_human_interaction_challenge(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "js_challenge", + get_waf_config_js_challenge(module.params["waf_config"]), + ) + setattr( + waf_config_details, "origin", get_waf_config_origin(module.params["waf_config"]) + ) + setattr( + waf_config_details, + "protection_settings", + get_waf_config_protection_settings(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "whitelists", + get_waf_config_whitelists(module.params["waf_config"]), + ) + return waf_config_details + + +def get_waf_config_for_update(module): + if not module.params.get("waf_config"): + return None + waf_config_details = WafConfig() + setattr( + waf_config_details, + "access_rules", + get_waf_config_access_rules(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "address_rate_limiting", + get_waf_config_address_rate_limiting(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "captchas", + get_waf_config_captchas(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "device_fingerprint_challenge", + get_waf_config_device_fingerprint_challenge(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "good_bots", + get_waf_config_good_bots(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "human_interaction_challenge", + get_waf_config_human_interaction_challenge(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "js_challenge", + get_waf_config_js_challenge(module.params["waf_config"]), + ) + setattr( + waf_config_details, "origin", get_waf_config_origin(module.params["waf_config"]) + ) + setattr( + waf_config_details, + "protection_rules", + get_waf_config_protection_rules(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "protection_settings", + get_waf_config_protection_settings(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "threat_feeds", + get_waf_config_threat_feeds(module.params["waf_config"]), + ) + setattr( + waf_config_details, + "whitelists", + get_waf_config_whitelists(module.params["waf_config"]), + ) + return waf_config_details + + +def get_waas_policy_create_model(module): + create_waas_policy_details = get_model_from_dict( + CreateWaasPolicyDetails, + module.params, + [ + "compartment_id", + "display_name", + "domain", + "additional_domains", + "freeform_tags", + "defined_tags", + ], + ) + + setattr(create_waas_policy_details, "origins", get_waas_origins(module)) + setattr(create_waas_policy_details, "policy_config", get_waas_policy_config(module)) + setattr(create_waas_policy_details, "waf_config", get_waf_config(module)) + return create_waas_policy_details + + +def get_resource_identifier_from_waas_work_request_response( + work_request_response, entity_type="waas", action_type="CREATED" +): + if not work_request_response: + return None + for work_request_resource in work_request_response.data.resources: + if ( + work_request_resource.entity_type == entity_type + and work_request_resource.action_type == action_type + ): + return work_request_resource.identifier + return None + + +def get_model_from_dict(model_class, params, attrs): + model = model_class() + if not (attrs and params): + return model + for attr in attrs: + if params.get(attr): + setattr(model, attr, params[attr]) + return model + + +def get_waas_policy_id_from_work_request_response( + work_request_response, entity_type="waas", action_type="CREATED" +): + if not work_request_response: + return None + logger.debug( + "Work request response: {0}".format(to_dict(work_request_response.data)) + ) + for work_request_resource in work_request_response.data.resources: + if ( + work_request_resource.entity_type == entity_type + and work_request_resource.action_type == action_type + ): + return work_request_resource.identifier + return None + + +def get_waas_policy_from_work_request_response(work_request_response, module, client): + waas_policy_id = get_waas_policy_id_from_work_request_response( + work_request_response + ) + if not waas_policy_id: + module.fail_json(msg="Cound not get the waas policy id from the work request.") + logger.debug( + "WAAS policy id from the work request response: {0}".format(waas_policy_id) + ) + waas_policy = oci_utils.call_with_backoff( + client.get_waas_policy, waas_policy_id=waas_policy_id + ).data + if not waas_policy: + module.fail_json("Could not get the waas policy resource after creation.") + if waas_policy.lifecycle_state in oci_utils.DEAD_STATES: + module.fail_json( + msg="WAAS policy created but in {0} state.".format( + waas_policy.lifecycle_state + ) + ) + return to_dict(waas_policy) + + +def get_waas_policy_from_summary_resource(waas_policy_summary, waas_client=None): + logger.debug("Waas policy summary resource: {0}".format(waas_policy_summary)) + if not waas_policy_summary: + return None + if not waas_client: + raise Exception( + "waas client required to get waas policy from summary resource." + ) + if isinstance(waas_policy_summary, dict): + waas_policy_id = waas_policy_summary.get("id") + else: + waas_policy_id = getattr(waas_policy_summary, "id", None) + if not waas_policy_id: + raise Exception("The waas policy summary resource does not have a valid id.") + return oci_utils.call_with_backoff( + waas_client.get_waas_policy, waas_policy_id=waas_policy_id + ).data + + +def get_waas_certificate_from_summary_resource( + waas_certificate_summary, waas_client=None +): + logger.debug( + "Waas certificate summary resource: {0}".format(waas_certificate_summary) + ) + if not waas_certificate_summary: + return None + if not waas_client: + raise Exception( + "waas client required to get waas certificate from summary resource." + ) + if isinstance(waas_certificate_summary, dict): + waas_certificate_id = waas_certificate_summary.get("id") + else: + waas_certificate_id = getattr(waas_certificate_summary, "id", None) + if not waas_certificate_id: + raise Exception( + "The waas certificate summary resource does not have a valid id." + ) + return oci_utils.call_with_backoff( + waas_client.get_certificate, certificate_id=waas_certificate_id + ).data + + +def list_waas_policies(waas_client, module): + return [ + oci_utils.call_with_backoff( + waas_client.get_waas_policy, waas_policy_id=waas_policy_summary.id + ).data + for waas_policy_summary in oci_utils.list_all_resources( + waas_client.list_waas_policies, + compartment_id=module.params.get("compartment_id"), + ) + ] + + +def list_certificates(waas_client, module): + return [ + oci_utils.call_with_backoff( + waas_client.get_certificate, certificate_id=waas_certificate_summary.id + ) + for waas_certificate_summary in oci_utils.list_all_resources( + waas_client.list_certificates, + compartment_id=module.params.get("compartment_id"), + ) + ] diff --git a/samples/block_volume/attach_connect_block_volume/sample.yaml b/samples/block_volume/attach_connect_block_volume/sample.yaml index e11a582..dab83b6 100644 --- a/samples/block_volume/attach_connect_block_volume/sample.yaml +++ b/samples/block_volume/attach_connect_block_volume/sample.yaml @@ -32,7 +32,7 @@ securitylist_name: "mysecuritylist" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance_hostname: "mytestinstance" volume_name: "my_test_volume" diff --git a/samples/compute/app_catalog/README.md b/samples/compute/app_catalog/README.md new file mode 100644 index 0000000..28e2a63 --- /dev/null +++ b/samples/compute/app_catalog/README.md @@ -0,0 +1,15 @@ +# Overview + +This sample shows how a public compute instance can be [launched](https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/launchinginstance.htm) and [accessed](https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/accessinginstance.htm) from the internet using SSH, through OCI ansible cloud modules. + +The sample +- generates a temporary host-specific SSH key-pair +- specifies the public key from that key-pair to connect to the instance during instance launch and +- demonstrates how the newly launched instance can be connected to using SSH. + +# Instructions + +To run the sample, after ensuring that you have the pre-requisites for OCI ansible cloud modules, please provide values (that are specific to your tenancy) for the following variables in the `vars` section of `sample.yaml`: +- instance_ad +- instance_compartment +- instance_image # provide an OL image diff --git a/samples/compute/app_catalog/sample.yaml b/samples/compute/app_catalog/sample.yaml new file mode 100644 index 0000000..506cb46 --- /dev/null +++ b/samples/compute/app_catalog/sample.yaml @@ -0,0 +1,112 @@ +--- +# Copyright (c) 2019 Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +- name: Launch a compute instance and connect to it using SSH + hosts: localhost + vars: + # common networking definitions + quad_zero_route: "0.0.0.0/0" + TCP_protocol: "6" + SSH_port: "22" + + vcn_name: "myappcatalogtestvcn" + vcn_cidr_block: "10.0.0.0/16" + vcn_dns_label: "mytestvcn" + + ig_name: "myinternetgatewayformytestvcn" + + route_table_name: "myroutetable" + # route all internet access to our Internet Gateway + route_table_rules: + - cidr_block: "{{ quad_zero_route }}" + network_entity_id: "{{ ig_id }}" + + + subnet_cidr: "10.0.0.48/28" + subnet_name: "mytestsubnet" + subnet_dns_label: "mytestsubnet" + + securitylist_name: "mysecuritylist" + instance_hostname: "myappcatalogtestinstance" + instance_name: "my_app_catalog_test_instance" + + ######################################### + # Tenancy specific configuration + # *Note* - Override the following variables based on your tenancy + # or set a valid value for the corresponding environment variable + ######################################### + instance_ad: "{{ lookup('env', 'SAMPLE_AD_NAME') }}" + instance_compartment: "{{ lookup('env', 'SAMPLE_COMPARTMENT_OCID') }}" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" + app_catalog_listing_id: "{{ lookup('env', 'SAMPLE_APP_CATALOG_LISTING_ID') }}" + app_catalog_image_ssh_user: "{{ lookup('env', 'SAMPLE_APP_CATALOG_SSH_USER') | default('opc', true) }}" + + tasks: + - import_tasks: setup.yaml + + - name: Launch an instance + oci_instance: + availability_domain: "{{ instance_ad }}" + compartment_id: "{{ instance_compartment }}" + name: "{{ instance_name }}" + shape: "{{ instance_shape }}" + source_details: + source_type: image + image_id: "{{ app_catalog_image_id }}" + vnic: + assign_public_ip: True + hostname_label: "{{ instance_hostname }}" + subnet_id: "{{ instance_subnet_id }}" + metadata: + ssh_authorized_keys: "{{ lookup('file', my_test_public_key ) }}" + register: result + + - name: Print instance details + debug: + msg: "Launched a new instance {{ result }}" + - set_fact: + instance_id: "{{result.instance.id }}" + + - name: Get the VNIC attachment details of instance + oci_vnic_attachment_facts: + compartment_id: "{{ instance_compartment }}" + instance_id: "{{ instance_id }}" + register: result + + - name: Get details of the VNIC + oci_vnic_facts: + id: "{{ result.vnic_attachments[0].vnic_id }}" + register: result + - set_fact: + instance_public_ip: "{{result.vnic.public_ip}}" + + - name: Print the public ip of the newly launched instance + debug: + msg: "Public IP of launched instance {{ instance_public_ip }}" + + - name: Wait (upto 5 minutes) for port 22 to become open + wait_for: + port: 22 + host: '{{ instance_public_ip }}' + state: started + delay: 10 + vars: + ansible_connection: local + + - name: Attempt a ssh connection to the newly launced instance + # Disable SSH's strict host key checking just for this one command invocation + command: ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -i {{ temp_certificates_path }}/private_key.pem {{ app_catalog_image_ssh_user }}@{{ instance_public_ip }} uname -a + retries: 5 + delay: 20 + register: result + until: result.rc == 0 + + - name: Print SSH response from launched instance + debug: + msg: "SSH response from instance -> {{ result.stdout_lines }}" + + - import_tasks: teardown.yaml diff --git a/samples/compute/app_catalog/setup.yaml b/samples/compute/app_catalog/setup.yaml new file mode 100644 index 0000000..a31b2a7 --- /dev/null +++ b/samples/compute/app_catalog/setup.yaml @@ -0,0 +1,156 @@ +--- +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +- name: Check pre-requisites + fail: + msg: "Environment variable {{item}} not set. Please declare an environment variable with an appropriate value for the sample to work." + when: item not in ansible_env + with_items: + - "SAMPLE_COMPARTMENT_OCID" + - "SAMPLE_AD_NAME" + - "SAMPLE_APP_CATALOG_LISTING_ID" + +- name: Create a temporary directory to house a temporary SSH keypair we will later use to connect to instance + tempfile: + state: directory + suffix: cert + register: result +- set_fact: + temp_certificates_path: "{{ result.path }}" +- name: Generate a Private Key + openssl_privatekey: + path: "{{ temp_certificates_path }}/private_key.pem" + type: RSA + size: 2048 +- set_fact: + my_test_public_key: "{{ temp_certificates_path }}/public_key.pem" +- name: Generate a Public Key + openssl_publickey: + path: "{{ my_test_public_key }}" + privatekey_path: "{{ temp_certificates_path }}/private_key.pem" + format: OpenSSH + +- name: Create a VCN + oci_vcn: + compartment_id: "{{ instance_compartment }}" + display_name: "{{ vcn_name }}" + cidr_block: "{{ vcn_cidr_block }}" + dns_label: "{{ vcn_dns_label }}" + register: result +- set_fact: + vcn_id: "{{ result.vcn.id }}" + +- name : Create a new Internet Gateway + oci_internet_gateway: + compartment_id: "{{ instance_compartment }}" + vcn_id: "{{ vcn_id }}" + name: "{{ ig_name }}" + enabled: 'yes' + state: 'present' + register: result +- set_fact: + ig_id: "{{ result.internet_gateway.id }}" + +- name: Create route table to connect internet gateway to the VCN + oci_route_table: + compartment_id: "{{ instance_compartment }}" + vcn_id: "{{ vcn_id }}" + name: "{{ route_table_name }}" + route_rules: "{{ route_table_rules }}" + state: 'present' + register: result +- set_fact: + rt_id: "{{ result.route_table.id }}" + +# Create a security list for allowing access to public instance +# Use a jinja2 template of the ingress and egress security rules to generate +# a templated version of the final rules. +- name: create ingress rules yaml body + template: src=./templates/ingress_security_rules.yaml.j2 dest=/tmp/instance_ingress_security_rules.yaml +- name: create egress yaml body + template: src=./templates/egress_security_rules.yaml.j2 dest=/tmp/instance_egress_security_rules.yaml +# Load the variables defined in the generated files +- name: load the variables defined in the ingress rules yaml body + include_vars: + file: /tmp/instance_ingress_security_rules.yaml + name: loaded_ingress +- name: print loaded_ingress + debug: + msg: "loaded ingress is {{loaded_ingress}}" +- name: load the variables defined in the egress rules yaml body + include_vars: + file: /tmp/instance_egress_security_rules.yaml + name: loaded_egress +- name: print loaded_egress + debug: + msg: "loaded egress is {{loaded_egress}}" +- name: Create a security list for allowing access to public instance + oci_security_list: + name: "{{ securitylist_name }}" + compartment_id: "{{ instance_compartment }}" + vcn_id: '{{ vcn_id }}' + ingress_security_rules: "{{ loaded_ingress.instance_ingress_security_rules }}" + egress_security_rules: "{{ loaded_egress.instance_egress_security_rules }}" + register: result +- set_fact: + instance_security_list_ocid: "{{ result.security_list.id }}" + +- name: Create a subnet to host the public instance. Link security_list and route_table. + oci_subnet: + availability_domain: "{{ instance_ad }}" + cidr_block: "{{ subnet_cidr }}" + compartment_id: "{{ instance_compartment }}" + display_name: "{{ subnet_name }}" + prohibit_public_ip_on_vnic: false + route_table_id: "{{ rt_id }}" + security_list_ids: [ "{{ instance_security_list_ocid }}" ] + vcn_id: '{{ vcn_id }}' + dns_label: "{{ subnet_dns_label }}" + register: result +- set_fact: + instance_subnet_id: "{{ result.subnet.id }}" + +- name: Get the app catalog listing + oci_app_catalog_listing_facts: + listing_id: "{{ app_catalog_listing_id }}" + register: app_catalog_listing_result + +- name: Get all the resource versions of the listing + oci_app_catalog_listing_resource_version_facts: + listing_id: "{{ app_catalog_listing_id }}" + register: all_resource_versions_result + +- debug: + msg: "{{ all_resource_versions_result }}" + +- set_fact: + resource_versions: "{{ all_resource_versions_result.app_catalog_listing_resource_versions }}" + latest_resource_version: "{{ all_resource_versions_result.app_catalog_listing_resource_versions[0].listing_resource_version }}" + app_catalog_image_id: "{{ all_resource_versions_result.app_catalog_listing_resource_versions[0].listing_resource_id }}" + +- name: Create an agreement for the listing + oci_app_catalog_listing_agreement: + listing_id: "{{ app_catalog_listing_id }}" + resource_version: "{{ latest_resource_version }}" + register: agreement_result + +- set_fact: + agreement: "{{ agreement_result.app_catalog_listing_agreement }}" + +- name: Create subscription if it does not exist + oci_app_catalog_subscription: + compartment_id: "{{ instance_compartment }}" + eula_link: "{{ agreement.eula_link }}" + listing_id: "{{ app_catalog_listing_id }}" + listing_resource_version: "{{ latest_resource_version }}" + oracle_terms_of_use_link: "{{ agreement.oracle_terms_of_use_link }}" + signature: "{{ agreement.signature }}" + time_retrieved: "{{ agreement.time_retrieved }}" + register: create_subscription_result + +- debug: + msg: "{{ create_subscription_result }}" \ No newline at end of file diff --git a/samples/compute/app_catalog/teardown.yaml b/samples/compute/app_catalog/teardown.yaml new file mode 100644 index 0000000..2b0930f --- /dev/null +++ b/samples/compute/app_catalog/teardown.yaml @@ -0,0 +1,37 @@ +--- +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +- name: Terminate the instance + oci_instance: + id: "{{ instance_id }}" + state: absent + +- name: Delete the subnet + oci_subnet: + id: "{{ instance_subnet_id }}" + state: absent + +- name: Delete the security list + oci_security_list: + id: "{{ instance_security_list_ocid }}" + state: absent + +- name: Delete the route table + oci_route_table: + id: "{{ rt_id }}" + state: absent + +- name : Delete the Internet Gateway + oci_internet_gateway: + id: "{{ ig_id }}" + state: absent + +- name: Delete the VCN + oci_vcn: + vcn_id: "{{ vcn_id }}" + state: absent + diff --git a/samples/compute/app_catalog/templates/egress_security_rules.yaml.j2 b/samples/compute/app_catalog/templates/egress_security_rules.yaml.j2 new file mode 100644 index 0000000..ed16ef5 --- /dev/null +++ b/samples/compute/app_catalog/templates/egress_security_rules.yaml.j2 @@ -0,0 +1,15 @@ +--- +# Copyright (c) 2019 Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. +instance_egress_security_rules: + # Allow ssh connections outside + - destination: "{{ quad_zero_route }}" + protocol: "{{ TCP_protocol }}" + tcp_options: + destination_port_range: + min: {{ SSH_port }} + max: {{ SSH_port }} + diff --git a/samples/compute/app_catalog/templates/ingress_security_rules.yaml.j2 b/samples/compute/app_catalog/templates/ingress_security_rules.yaml.j2 new file mode 100644 index 0000000..4eca4eb --- /dev/null +++ b/samples/compute/app_catalog/templates/ingress_security_rules.yaml.j2 @@ -0,0 +1,15 @@ +--- +# Copyright (c) 2019 Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. +instance_ingress_security_rules: + # Allow incoming SSH connections + - source: "{{ quad_zero_route }}" + protocol: "{{ TCP_protocol }}" + tcp_options: + destination_port_range: + min: {{ SSH_port }} + max: {{ SSH_port }} + diff --git a/samples/compute/create_instance_pool/sample.yaml b/samples/compute/create_instance_pool/sample.yaml index 2db54c1..8e24c06 100644 --- a/samples/compute/create_instance_pool/sample.yaml +++ b/samples/compute/create_instance_pool/sample.yaml @@ -32,7 +32,7 @@ securitylist_name: "mysecuritylist" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance_display_name: "mytestinstance" ######################################### diff --git a/samples/compute/instance-console-connections-and-capture-console-history/sample.yaml b/samples/compute/instance-console-connections-and-capture-console-history/sample.yaml index e5c264c..f37d101 100644 --- a/samples/compute/instance-console-connections-and-capture-console-history/sample.yaml +++ b/samples/compute/instance-console-connections-and-capture-console-history/sample.yaml @@ -32,13 +32,13 @@ securitylist_name: "mysecuritylist" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance_hostname: "mytestinstance" ######################################### # Tenancy specific configuration # *Note* - Override the following variables based on your tenancy - # or set a valid value for the corresponding environment variable + # or set a valid value for the corresponding environment variable ######################################### instance_ad: "{{ lookup('env', 'SAMPLE_AD_NAME') }}" instance_compartment: "{{ lookup('env', 'SAMPLE_COMPARTMENT_OCID') }}" @@ -104,7 +104,7 @@ msg: "Instance console connection string - {{result.instance_console_connection.connection_string}} " - set_fact: - # Since this sample uses a custom private key that is not in the default locations where ssh looks for identify files for PK auth, + # Since this sample uses a custom private key that is not in the default locations where ssh looks for identify files for PK auth, # append the custom private key to the proxy portion of the SSH invocation string returned by oci_instance_console_connection # (Note - this step is not needed if you use your default SSH public key as the `public_key` while creating the instance console connection # using oci_instance_console_connection) diff --git a/samples/compute/launch_compute_instance/sample.yaml b/samples/compute/launch_compute_instance/sample.yaml index 6080077..3090974 100644 --- a/samples/compute/launch_compute_instance/sample.yaml +++ b/samples/compute/launch_compute_instance/sample.yaml @@ -32,7 +32,7 @@ securitylist_name: "mysecuritylist" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance_hostname: "mytestinstance" ######################################### diff --git a/samples/compute/nat_gateway_configuration/sample.yaml b/samples/compute/nat_gateway_configuration/sample.yaml index b52ee54..c0803a3 100644 --- a/samples/compute/nat_gateway_configuration/sample.yaml +++ b/samples/compute/nat_gateway_configuration/sample.yaml @@ -43,7 +43,7 @@ public_subnet_instance_name: "my_bastion_instance_for_{{vcn_name}}" private_subnet_instance_name: "my_private_instance_in_{{private_subnet_name}}" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" public_subnet_instance_hostname: "mypublicinstance" private_subnet_instance_hostname: "myprivateinstance" diff --git a/samples/compute/nat_instance_configuration/sample.yaml b/samples/compute/nat_instance_configuration/sample.yaml index e3d5b3e..0ff67fa 100644 --- a/samples/compute/nat_instance_configuration/sample.yaml +++ b/samples/compute/nat_instance_configuration/sample.yaml @@ -42,7 +42,7 @@ public_subnet_instance_name: "my_nat_instance_for_{{vcn_name}}" private_subnet_instance_name: "my_private_instance_in_{{private_subnet_name}}" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" public_subnet_instance_hostname: "mypublicinstance" private_subnet_instance_hostname: "myprivateinstance" @@ -54,7 +54,7 @@ ######################################### # Tenancy specific configuration # *Note* - Override the following variables based on your tenancy - # or set a valid value for the corresponding environment variable + # or set a valid value for the corresponding environment variable ######################################### instance_ad: "{{ lookup('env', 'SAMPLE_AD_NAME') }}" instance_compartment: "{{ lookup('env', 'SAMPLE_COMPARTMENT_OCID') }}" @@ -94,7 +94,7 @@ - name: Print sample SSH invocation to test if internet access is available in the private instance command: 'ssh {{ ssh_disable_strict_host_key_checking_args }} {{ ssh_credentials_arg }} -o ProxyCommand="ssh {{ ssh_disable_strict_host_key_checking_args }} {{ ssh_credentials_arg }} -W %h:%p -q {{ ssh_user }}@{{ public_instance_public_ip }}" {{ ssh_user }}@{{ private_instance_private_ip }} ping -c2 oracle.com' register: result - + - name: Print ping response from the private instance debug: msg: "{{ result.stdout_lines }}" diff --git a/samples/compute/service_gateway/sample.yaml b/samples/compute/service_gateway/sample.yaml index 911878d..9fe9e90 100644 --- a/samples/compute/service_gateway/sample.yaml +++ b/samples/compute/service_gateway/sample.yaml @@ -100,7 +100,7 @@ public_subnet_instance_name: "my_bastion_instance_for_{{vcn_name}}" private_subnet_instance_name: "my_private_instance_in_{{private_subnet_name}}" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" public_subnet_instance_hostname: "mybastioninstance" private_subnet_instance_hostname: "myprivateinstance" diff --git a/samples/file_storage/create_and_mount_file_system/sample.yaml b/samples/file_storage/create_and_mount_file_system/sample.yaml index ac59872..ee01429 100644 --- a/samples/file_storage/create_and_mount_file_system/sample.yaml +++ b/samples/file_storage/create_and_mount_file_system/sample.yaml @@ -34,7 +34,7 @@ first_instance_hostname_label: 'instancehl1' second_instance_hostname_label: 'instancehl2' - instance_shape: 'VM.Standard1.1' + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" first_instance_name: 'first_instance' second_instance_name: 'second_instance' nfs_utils_script: './files/nfs-utils' diff --git a/samples/file_storage/multiple_file_systems_with_mount_targets/sample.yaml b/samples/file_storage/multiple_file_systems_with_mount_targets/sample.yaml index d2fabfc..d08b957 100644 --- a/samples/file_storage/multiple_file_systems_with_mount_targets/sample.yaml +++ b/samples/file_storage/multiple_file_systems_with_mount_targets/sample.yaml @@ -38,7 +38,7 @@ mt1_fs2_export_path: '/mt1_fs2_path' instance_hostname_label: 'instancehl' - instance_shape: 'VM.Standard1.1' + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance_name: 'sample_instance' ######################################### # Tenancy specific configuration diff --git a/samples/iam/iam-use-instance-principal-auth/instance-principal-test.sh b/samples/iam/iam-use-instance-principal-auth/instance-principal-test.sh old mode 100644 new mode 100755 diff --git a/samples/iam/iam-use-instance-principal-auth/list-compute-instances.yaml b/samples/iam/iam-use-instance-principal-auth/list-compute-instances.yaml deleted file mode 100644 index 4f64ab0..0000000 --- a/samples/iam/iam-use-instance-principal-auth/list-compute-instances.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -# Copyright (c) 2018, Oracle and/or its affiliates. -# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# Apache License v2.0 -# See LICENSE.TXT for details. - -- name : List all compute instances in Ansible compartment - connection: local - hosts: localhost - tasks: - - name: Create bucket - oci_instance_facts: - # pick the compartment_id from the environment variable SAMPLE_COMPARTMENT_OCID - compartment_id: "{{ lookup('env', 'SAMPLE_COMPARTMENT_OCID') }}" - register: currinstances - - debug: - msg: "{{currinstances}}" - diff --git a/samples/iam/iam-use-instance-principal-auth/sample.yaml b/samples/iam/iam-use-instance-principal-auth/sample.yaml index 6d68cb0..5ebf4fe 100644 --- a/samples/iam/iam-use-instance-principal-auth/sample.yaml +++ b/samples/iam/iam-use-instance-principal-auth/sample.yaml @@ -37,7 +37,7 @@ securitylist_name: "mysecuritylist" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance_hostname: "mytestinstanceprincipalauth" ######################################### diff --git a/samples/load_balancing/create_load_balancer/sample.yaml b/samples/load_balancing/create_load_balancer/sample.yaml index 84198a6..0c6ee5d 100644 --- a/samples/load_balancing/create_load_balancer/sample.yaml +++ b/samples/load_balancing/create_load_balancer/sample.yaml @@ -26,7 +26,7 @@ sample_app_server_instance_one_name: 'AS-1' sample_app_server_instance_two_name: 'AS-2' - sample_app_server_shape: 'VM.Standard1.1' + sample_app_server_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" lb_name: "sample_load_balancer" sample_shape: "100Mbps" diff --git a/samples/networking/private_subnets_with_vpn/sample.yaml b/samples/networking/private_subnets_with_vpn/sample.yaml index 05e5796..99dae7f 100644 --- a/samples/networking/private_subnets_with_vpn/sample.yaml +++ b/samples/networking/private_subnets_with_vpn/sample.yaml @@ -34,7 +34,7 @@ subnet1_dns_label: "mytestsubnet1" subnet2_dns_label: "mytestsubnet2" - instance_shape: "VM.Standard1.1" + instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" instance1_name: "test_instance_1" instance2_name: "test_instance_2" diff --git a/samples/solutions/secure-mongodb-deployment/roles/bastion/vars/main.yml b/samples/solutions/secure-mongodb-deployment/roles/bastion/vars/main.yml index 20c5124..2b8d0a2 100644 --- a/samples/solutions/secure-mongodb-deployment/roles/bastion/vars/main.yml +++ b/samples/solutions/secure-mongodb-deployment/roles/bastion/vars/main.yml @@ -6,7 +6,7 @@ # See LICENSE.TXT for details. bastion_image_ocid: "{{ lookup('env', 'SAMPLE_OL_IMAGE_OCID') }}" -bastion_shape: "VM.Standard1.1" +bastion_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" bastion_availability_domain: "{{ lookup('env', 'SAMPLE_AD2_NAME') }}" demo_bastion_subnet_name: "{{demo_var_prefix}}_bastion_subnet" diff --git a/samples/solutions/secure-mongodb-deployment/roles/mongo/vars/main.yml b/samples/solutions/secure-mongodb-deployment/roles/mongo/vars/main.yml index 0b529f8..7670772 100644 --- a/samples/solutions/secure-mongodb-deployment/roles/mongo/vars/main.yml +++ b/samples/solutions/secure-mongodb-deployment/roles/mongo/vars/main.yml @@ -12,7 +12,7 @@ mongodb_image_id: "{{ lookup('env', 'SAMPLE_OL_IMAGE_OCID') }}" availability_domain_1: "{{ lookup('env', 'SAMPLE_AD1_NAME') }}" availability_domain_2: "{{ lookup('env', 'SAMPLE_AD2_NAME') }}" -shape: 'VM.Standard1.1' +shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" mongodb_script: './files/mongodb' diff --git a/samples/solutions/secure-mongodb-deployment/roles/nat_instance/tasks/templates/demo_public_subnet_egress_security_rules.yaml.j2 b/samples/solutions/secure-mongodb-deployment/roles/nat_instance/tasks/templates/demo_public_subnet_egress_security_rules.yaml.j2 deleted file mode 100644 index 6a67b9c..0000000 --- a/samples/solutions/secure-mongodb-deployment/roles/nat_instance/tasks/templates/demo_public_subnet_egress_security_rules.yaml.j2 +++ /dev/null @@ -1,28 +0,0 @@ -demo_public_subnet_egress_security_rules: - # Allow app-servers to access MongoDB - - destination: "{{ demo_private_subnet_mongo_ad1_cidr }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ MONGODB_port }} - max: {{ MONGODB_port }} - - destination: "{{ demo_private_subnet_mongo_ad2_cidr }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ MONGODB_port }} - max: {{ MONGODB_port }} - # Allow access to HTTP(S) for cloud-init (yum, pip to work) - - destination: "{{ quad_zero_route }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTP_port }} - max: {{ HTTP_port }} - - destination: "{{ quad_zero_route }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTPS_port }} - max: {{ HTTPS_port }} - diff --git a/samples/solutions/secure-mongodb-deployment/roles/nat_instance/tasks/templates/demo_public_subnet_ingress_security_rules.yaml.j2 b/samples/solutions/secure-mongodb-deployment/roles/nat_instance/tasks/templates/demo_public_subnet_ingress_security_rules.yaml.j2 deleted file mode 100644 index a581f16..0000000 --- a/samples/solutions/secure-mongodb-deployment/roles/nat_instance/tasks/templates/demo_public_subnet_ingress_security_rules.yaml.j2 +++ /dev/null @@ -1,47 +0,0 @@ -demo_public_subnet_ingress_security_rules: - - source: "{{ demo_private_subnet_mongo_ad1_cidr }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTP_port }} - max: {{ HTTP_port }} - - source: "{{ demo_private_subnet_mongo_ad1_cidr }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTPS_port }} - max: {{ HTTPS_port }} - - source: "{{ demo_private_subnet_mongo_ad2_cidr }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTP_port }} - max: {{ HTTP_port }} - - source: "{{ demo_private_subnet_mongo_ad1_cidr }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTPS_port }} - max: {{ HTTPS_port }} - # HTTP - - source: "{{ quad_zero_route }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTP_port }} - max: {{ HTTP_port }} - # SSL/TLS - - source: "{{ quad_zero_route }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ HTTPS_port }} - max: {{ HTTPS_port }} - # Enable SSH access from Bastion - - source: "{{ bastion_subnet_cidr_block }}" - protocol: "{{ TCP_protocol }}" - tcp_options: - destination_port_range: - min: {{ SSH_port }} - max: {{ SSH_port }} - diff --git a/samples/solutions/secure-mongodb-deployment/roles/nat_instance/vars/main.yml b/samples/solutions/secure-mongodb-deployment/roles/nat_instance/vars/main.yml index b0c616e..ba5e72f 100644 --- a/samples/solutions/secure-mongodb-deployment/roles/nat_instance/vars/main.yml +++ b/samples/solutions/secure-mongodb-deployment/roles/nat_instance/vars/main.yml @@ -14,4 +14,4 @@ demo_public_subnet_security_list_name: "{{ demo_var_prefix }}_public_subnet" nat_instance_name: "{{ demo_var_prefix }}_nat_instance_for_mongodb_setup" nat_instance_image_ocid: "{{ lookup('env', 'SAMPLE_OL_IMAGE_OCID') }}" -nat_instance_shape: "VM.Standard1.1" +nat_instance_shape: "{{ lookup('env', 'SAMPLE_INSTANCE_SHAPE') | default('VM.Standard2.1', true) }}" diff --git a/test/units/oci_test_backup_facts.py b/test/units/oci_test_backup_facts.py deleted file mode 100644 index bfd0b85..0000000 --- a/test/units/oci_test_backup_facts.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright (c) 2018, Oracle and/or its affiliates. -# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# Apache License v2.0 -# See LICENSE.TXT for details. - -import pytest -from nose.plugins.skip import SkipTest -import logging -from ansible.modules.cloud.oracle import oci_backup_facts -from ansible.module_utils.oracle import oci_utils - - -try: - import oci - from oci.database.models import Backup - from oci.exceptions import ServiceError -except ImportError: - raise SkipTest("test_oci_backup_facts.py requires `oci` module") - - -class FakeModule(object): - def __init__(self, **kwargs): - self.params = kwargs - - def fail_json(self, *args, **kwargs): - self.exit_args = args - self.exit_kwargs = kwargs - raise Exception(kwargs["msg"]) - - def exit_json(self, *args, **kwargs): - self.exit_args = args - self.exit_kwargs = kwargs - - -@pytest.fixture() -def db_client(mocker): - mock_db_client = mocker.patch("oci.database.database_client.DatabaseClient") - return mock_db_client.return_value - - -@pytest.fixture() -def list_all_resources_patch(mocker): - return mocker.patch.object(oci_utils, "list_all_resources") - - -def setUpModule(): - logging.basicConfig( - filename="/tmp/oci_ansible_module.log", filemode="a", level=logging.INFO - ) - oci_backup_facts.set_logger(logging) - - -def test_list_backups_list_by_compartment_id(db_client, list_all_resources_patch): - module = get_module(dict({"compartment_id": "ocid1.compartment.aaaa"})) - list_all_resources_patch.return_value = get_backups() - result = oci_backup_facts.list_backups(db_client, module) - assert len(result["backups"]) is 2 - - -def test_list_backups_list_by_database_id(db_client, list_all_resources_patch): - module = get_module(dict({"database_id": "ocid1.database.aaaa"})) - list_all_resources_patch.return_value = get_backups() - result = oci_backup_facts.list_backups(db_client, module) - assert len(result["backups"]) is 2 - - -def test_list_backups_list_specific(db_client): - module = get_module(dict({"backup_id": "ocid1.backup.aaaa"})) - backup = get_backup() - db_client.get_backup.return_value = get_response(200, None, backup, None) - result = oci_backup_facts.list_backups(db_client, module) - assert result["backups"][0]["display_name"] is backup.display_name - - -def test_list_db_systems_service_error(db_client): - error_message = "Internal Server Error" - module = get_module(dict({"backup_id": "ocid1.backup.aaaa"})) - db_client.get_db_system.side_effect = ServiceError( - 499, "InternalServerError", dict(), error_message - ) - try: - oci_backup_facts.list_backups(db_client, module) - except Exception as ex: - assert error_message in ex.args[0] - - -def get_backups(): - backups = [] - backup1 = Backup() - backup1.display_name = "ansible-backup1" - backup2 = Backup() - backup2.display_name = "ansible-backup2" - backups.append(backup1) - backups.append(backup2) - return backups - - -def get_backup(): - backup = Backup() - backup.display_name = "ansible-backup" - return backup - - -def get_response(status, header, data, request): - return oci.Response(status, header, data, request) - - -def get_module(additional_properties): - params = dict() - params.update(additional_properties) - module = FakeModule(**params) - return module diff --git a/test/units/test_oci_app_catalog_listing_facts.py b/test/units/test_oci_app_catalog_listing_facts.py index 4a1907b..30fae99 100644 --- a/test/units/test_oci_app_catalog_listing_facts.py +++ b/test/units/test_oci_app_catalog_listing_facts.py @@ -50,12 +50,12 @@ def call_with_backoff_patch(mocker): def get_app_catalog_listing(**kwargs): - app_catalog_subscription = AppCatalogListing( + app_catalog_listing = AppCatalogListing( listing_id="ocid1.appcataloglisting.oc1..xxxxxEXAMPLExxxxx" ) for attr, val in six.iteritems(kwargs): - setattr(app_catalog_subscription, attr, val) - return app_catalog_subscription + setattr(app_catalog_listing, attr, val) + return app_catalog_listing def get_app_catalog_listings(): diff --git a/test/units/test_oci_bucket_facts.py b/test/units/test_oci_bucket_facts.py index e30ab73..6db9a92 100644 --- a/test/units/test_oci_bucket_facts.py +++ b/test/units/test_oci_bucket_facts.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. +# Copyright (c) 2017, 2018, 2019, Oracle and/or its affiliates. # This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # Apache License v2.0 @@ -67,7 +67,7 @@ def test_list_buckets_success(object_storage_client, list_all_resources_patch): bucket_summaries.append(bucket_summary_1) bucket_summaries.append(bucket_summary_2) list_all_resources_patch.return_value = bucket_summaries - result = oci_bucket_facts.list_buckets(object_storage_client, get_module()) + result = oci_bucket_facts.list_buckets(object_storage_client, get_module(), {}, {}) assert "Bucket1" in result.__repr__() @@ -78,7 +78,7 @@ def test_list_buckets_failure(object_storage_client): 404, "NamespaceNotFound", dict(), error_message ) try: - oci_bucket_facts.list_buckets(object_storage_client, get_module()) + oci_bucket_facts.list_buckets(object_storage_client, get_module(), {}, {}) except Exception as ex: assert error_message in ex.args[0] @@ -89,7 +89,7 @@ def test_list_buckets_failure_timeout_error(object_storage_client): error_message ) try: - oci_bucket_facts.list_buckets(object_storage_client, get_module()) + oci_bucket_facts.list_buckets(object_storage_client, get_module(), {}, {}) except Exception as ex: assert error_message in ex.args[0] diff --git a/test/units/test_oci_identity_provider_facts.py b/test/units/test_oci_identity_provider_facts.py new file mode 100644 index 0000000..a33932a --- /dev/null +++ b/test/units/test_oci_identity_provider_facts.py @@ -0,0 +1,168 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils import six +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_identity_provider_facts + +try: + import oci + from oci.util import to_dict + from oci.identity.models import Saml2IdentityProvider + from oci.exceptions import ServiceError +except ImportError: + raise SkipTest("test_oci_identity_provider_facts.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def identity_client(mocker): + mock_identity_client = mocker.patch("oci.identity.identity_client.IdentityClient") + return mock_identity_client.return_value + + +@pytest.fixture() +def list_all_resources_patch(mocker): + return mocker.patch.object(oci_utils, "list_all_resources") + + +@pytest.fixture() +def call_with_backoff_patch(mocker): + return mocker.patch.object(oci_utils, "call_with_backoff") + + +def get_identity_provider(**kwargs): + identity_provider = Saml2IdentityProvider( + id="ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx" + ) + for attr, val in six.iteritems(kwargs): + setattr(identity_provider, attr, val) + return identity_provider + + +def get_identity_providers(): + return [ + get_identity_provider( + id="ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx1", protocol="SAML2" + ), + get_identity_provider( + id="ocid1.saml2idp.oc1..xxxxxEXAMPLExxxxx2", protocol="SAML2" + ), + ] + + +def get_module(**kwargs): + params = {} + params.update(kwargs) + module = FakeModule(**params) + return module + + +def get_response(status=200, headers=None, data=None, request=None): + if not headers: + headers = dict() + return oci.Response(status, headers, data, request) + + +def test_get_identity_provider_raises_service_error( + identity_client, call_with_backoff_patch +): + call_with_backoff_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_identity_provider_facts.get_identity_provider(identity_client, get_module()) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_get_identity_provider(identity_client, call_with_backoff_patch): + identity_provider = get_identity_provider() + call_with_backoff_patch.return_value = get_response(data=identity_provider) + result = oci_identity_provider_facts.get_identity_provider( + identity_client, get_module() + ) + assert len(result) == 1 + call_with_backoff_patch.assert_called_once() + assert result[0]["id"] == identity_provider.id + + +def test_list_identity_providers_raises_service_error( + identity_client, list_all_resources_patch +): + list_all_resources_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_identity_provider_facts.list_identity_providers( + identity_client, get_module() + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_list_identity_providers_when_no_identity_providers_exist( + identity_client, list_all_resources_patch +): + list_all_resources_patch.return_value = [] + result = oci_identity_provider_facts.list_identity_providers( + identity_client, get_module() + ) + assert len(result) == 0 + + +def test_list_identity_providers_when_identity_providers_exist( + identity_client, list_all_resources_patch +): + identity_providers = get_identity_providers() + list_all_resources_patch.return_value = identity_providers + result = oci_identity_provider_facts.list_identity_providers( + identity_client, get_module() + ) + assert len(result) == 2 + assert list_all_resources_patch.call_count == 1 + + +def test_list_identity_providers_filter_by_name( + identity_client, list_all_resources_patch +): + module = get_module( + name="testidentityprovider", + protocol="SAML2", + compartment_id="ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx", + ) + list_all_resources_patch.return_value = [ + get_identity_provider(name="testidentityprovider") + ] + result = oci_identity_provider_facts.list_identity_providers( + identity_client, module + ) + assert len(result) == 1 + list_all_resources_patch.assert_called_with( + identity_client.list_identity_providers, + protocol="SAML2", + compartment_id="ocid1.tenancy.oc1..xxxxxEXAMPLExxxxx", + name="testidentityprovider", + ) diff --git a/test/units/test_oci_waas_certificate_facts.py b/test/units/test_oci_waas_certificate_facts.py new file mode 100644 index 0000000..c594dd9 --- /dev/null +++ b/test/units/test_oci_waas_certificate_facts.py @@ -0,0 +1,168 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_waas_certificate_facts + +try: + import oci + from oci.util import to_dict + from oci.response import Response + from oci.exceptions import ServiceError + from oci.waas.models import CertificateSummary +except ImportError: + raise SkipTest("test_oci_waas_certificate_facts.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def waas_client(mocker): + mock_waas_client = mocker.patch("oci.waas.waas_client.WaasClient") + return mock_waas_client.return_value + + +@pytest.fixture() +def list_all_resources_patch(mocker): + return mocker.patch.object(oci_utils, "list_all_resources") + + +@pytest.fixture() +def call_with_backoff_patch(mocker): + return mocker.patch.object(oci_utils, "call_with_backoff") + + +def get_module(**kwargs): + params = {} + params.update(kwargs) + module = FakeModule(**params) + return module + + +def get_certificates(): + return [ + CertificateSummary( + id="ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx1", display_name="testname1" + ), + CertificateSummary( + id="ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx2", display_name="testname2" + ), + ] + + +def get_response(status=200, headers=None, data=None, request=None): + if not headers: + headers = dict() + return oci.Response(status, headers, data, request) + + +def test_list_certificates_raises_service_error(waas_client, list_all_resources_patch): + list_all_resources_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_certificate_facts.list_certificates( + waas_client, + get_module(compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx"), + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_list_certificates_calls_list_all_resources_with_correct_parameters( + waas_client, list_all_resources_patch +): + id = [ + "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx1", + "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx2", + ] + display_name = ["testname1" "testname2"] + lifecycle_state = ["ACTIVE", "CREATING"] + module = get_module( + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + sort_by="timeCreated", + sort_order="DESC", + id=id, + display_name=display_name, + lifecycle_state=lifecycle_state, + time_created_greater_than_or_equal_to="2019-04-02T17:12:42.454000+00:00", + time_created_less_than="2019-04-02T17:12:42.454000+00:00", + ) + list_all_resources_patch.return_value = [] + oci_waas_certificate_facts.list_certificates(waas_client, module) + list_all_resources_patch.assert_called_once() + list_all_resources_patch.assert_called_with( + waas_client.list_certificates, + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + sort_by="timeCreated", + sort_order="DESC", + id=id, + display_name=display_name, + lifecycle_state=lifecycle_state, + time_created_greater_than_or_equal_to="2019-04-02T17:12:42.454000+00:00", + time_created_less_than="2019-04-02T17:12:42.454000+00:00", + ) + + +def test_list_certificates_calls_get_certificate( + waas_client, list_all_resources_patch, call_with_backoff_patch +): + module = get_module(compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx") + certificates = get_certificates() + list_all_resources_patch.return_value = certificates + oci_waas_certificate_facts.list_certificates(waas_client, module) + list_all_resources_patch.assert_called_once() + assert call_with_backoff_patch.call_count == 2 + call_with_backoff_patch.assert_any_call( + waas_client.get_certificate, certificate_id=certificates[0].id + ) + call_with_backoff_patch.assert_any_call( + waas_client.get_certificate, certificate_id=certificates[1].id + ) + + +def test_get_certificate_raises_service_error(waas_client, call_with_backoff_patch): + call_with_backoff_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_certificate_facts.get_certificate( + waas_client, + get_module(certificate_id="ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx"), + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_get_certificate_calls_call_with_backoff_with_correct_parameters( + waas_client, call_with_backoff_patch +): + certificate_id = "ocid1.waascertificate.oc1..xxxxxEXAMPLExxxxx" + module = get_module(certificate_id=certificate_id) + call_with_backoff_patch.return_value = get_response(data=None) + oci_waas_certificate_facts.get_certificate(waas_client, module) + call_with_backoff_patch.assert_called_once() + call_with_backoff_patch.assert_called_with( + waas_client.get_certificate, certificate_id=certificate_id + ) diff --git a/test/units/test_oci_waas_edge_subnet_facts.py b/test/units/test_oci_waas_edge_subnet_facts.py new file mode 100644 index 0000000..9ab5643 --- /dev/null +++ b/test/units/test_oci_waas_edge_subnet_facts.py @@ -0,0 +1,73 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_waas_edge_subnet_facts + +try: + import oci + from oci.util import to_dict + from oci.exceptions import ServiceError +except ImportError: + raise SkipTest("test_oci_waas_edge_subnet_facts.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def waas_client(mocker): + mock_waas_client = mocker.patch("oci.waas.waas_client.WaasClient") + return mock_waas_client.return_value + + +@pytest.fixture() +def list_all_resources_patch(mocker): + return mocker.patch.object(oci_utils, "list_all_resources") + + +def get_module(**kwargs): + params = {} + params.update(kwargs) + module = FakeModule(**params) + return module + + +def test_list_edge_subnets_raises_service_error(waas_client, list_all_resources_patch): + list_all_resources_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_edge_subnet_facts.list_edge_subnets(waas_client, get_module()) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_list_edge_subnets_calls_list_all_resources_with_correct_parameters( + waas_client, list_all_resources_patch +): + module = get_module(sort_by="region", sort_order="DESC") + list_all_resources_patch.return_value = [] + oci_waas_edge_subnet_facts.list_edge_subnets(waas_client, module) + list_all_resources_patch.assert_called_once() + list_all_resources_patch.assert_called_with( + waas_client.list_edge_subnets, sort_by="region", sort_order="DESC" + ) diff --git a/test/units/test_oci_waas_policy_facts.py b/test/units/test_oci_waas_policy_facts.py new file mode 100644 index 0000000..40ec3f8 --- /dev/null +++ b/test/units/test_oci_waas_policy_facts.py @@ -0,0 +1,168 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_waas_policy_facts + +try: + import oci + from oci.util import to_dict + from oci.response import Response + from oci.exceptions import ServiceError + from oci.waas.models import WaasPolicySummary +except ImportError: + raise SkipTest("test_oci_waas_policy_facts.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def waas_client(mocker): + mock_waas_client = mocker.patch("oci.waas.waas_client.WaasClient") + return mock_waas_client.return_value + + +@pytest.fixture() +def list_all_resources_patch(mocker): + return mocker.patch.object(oci_utils, "list_all_resources") + + +@pytest.fixture() +def call_with_backoff_patch(mocker): + return mocker.patch.object(oci_utils, "call_with_backoff") + + +def get_module(**kwargs): + params = {} + params.update(kwargs) + module = FakeModule(**params) + return module + + +def get_waas_policies(): + return [ + WaasPolicySummary( + id="ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx1", display_name="testname1" + ), + WaasPolicySummary( + id="ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx2", display_name="testname2" + ), + ] + + +def get_response(status=200, headers=None, data=None, request=None): + if not headers: + headers = dict() + return oci.Response(status, headers, data, request) + + +def test_list_waas_policies_raises_service_error(waas_client, list_all_resources_patch): + list_all_resources_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_policy_facts.list_waas_policies( + waas_client, + get_module(compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx"), + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_list_waas_policies_calls_list_all_resources_with_correct_parameters( + waas_client, list_all_resources_patch +): + id = [ + "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx1", + "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx2", + ] + display_name = ["testname1" "testname2"] + lifecycle_state = ["ACTIVE", "CREATING"] + module = get_module( + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + sort_by="timeCreated", + sort_order="DESC", + id=id, + display_name=display_name, + lifecycle_state=lifecycle_state, + time_created_greater_than_or_equal_to="2019-04-02T17:12:42.454000+00:00", + time_created_less_than="2019-04-02T17:12:42.454000+00:00", + ) + list_all_resources_patch.return_value = [] + oci_waas_policy_facts.list_waas_policies(waas_client, module) + list_all_resources_patch.assert_called_once() + list_all_resources_patch.assert_called_with( + waas_client.list_waas_policies, + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + sort_by="timeCreated", + sort_order="DESC", + id=id, + display_name=display_name, + lifecycle_state=lifecycle_state, + time_created_greater_than_or_equal_to="2019-04-02T17:12:42.454000+00:00", + time_created_less_than="2019-04-02T17:12:42.454000+00:00", + ) + + +def test_list_waas_policies_calls_get_waas_policy( + waas_client, list_all_resources_patch, call_with_backoff_patch +): + module = get_module(compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx") + waas_policies = get_waas_policies() + list_all_resources_patch.return_value = waas_policies + oci_waas_policy_facts.list_waas_policies(waas_client, module) + list_all_resources_patch.assert_called_once() + assert call_with_backoff_patch.call_count == 2 + call_with_backoff_patch.assert_any_call( + waas_client.get_waas_policy, waas_policy_id=waas_policies[0].id + ) + call_with_backoff_patch.assert_any_call( + waas_client.get_waas_policy, waas_policy_id=waas_policies[1].id + ) + + +def test_get_waas_policy_raises_service_error(waas_client, call_with_backoff_patch): + call_with_backoff_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_policy_facts.get_waas_policy( + waas_client, + get_module(waas_policy_id="ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx"), + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_get_waas_policy_calls_call_with_backoff_with_correct_parameters( + waas_client, call_with_backoff_patch +): + waas_policy_id = "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx" + module = get_module(waas_policy_id=waas_policy_id) + call_with_backoff_patch.return_value = get_response(data=None) + oci_waas_policy_facts.get_waas_policy(waas_client, module) + call_with_backoff_patch.assert_called_once() + call_with_backoff_patch.assert_called_with( + waas_client.get_waas_policy, waas_policy_id=waas_policy_id + ) diff --git a/test/units/test_oci_waas_recommendation_facts.py b/test/units/test_oci_waas_recommendation_facts.py new file mode 100644 index 0000000..d8614dc --- /dev/null +++ b/test/units/test_oci_waas_recommendation_facts.py @@ -0,0 +1,81 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_waas_recommendation_facts + +try: + import oci + from oci.util import to_dict + from oci.exceptions import ServiceError +except ImportError: + raise SkipTest("test_oci_waas_recommendation_facts.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def waas_client(mocker): + mock_waas_client = mocker.patch("oci.waas.waas_client.WaasClient") + return mock_waas_client.return_value + + +@pytest.fixture() +def list_all_resources_patch(mocker): + return mocker.patch.object(oci_utils, "list_all_resources") + + +def get_module(**kwargs): + params = {} + params.update(kwargs) + module = FakeModule(**params) + return module + + +def test_list_recommendations_raises_service_error( + waas_client, list_all_resources_patch +): + list_all_resources_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_recommendation_facts.list_recommendations( + waas_client, + get_module(waas_policy_id="ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx"), + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_list_recommendations_calls_list_all_resources_with_correct_parameters( + waas_client, list_all_resources_patch +): + waas_policy_id = "ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx" + module = get_module(waas_policy_id=waas_policy_id, recommended_action="BLOCK") + list_all_resources_patch.return_value = [] + oci_waas_recommendation_facts.list_recommendations(waas_client, module) + list_all_resources_patch.assert_called_once() + list_all_resources_patch.assert_called_with( + waas_client.list_recommendations, + waas_policy_id=waas_policy_id, + recommended_action="BLOCK", + ) diff --git a/test/units/test_oci_waas_work_request.py b/test/units/test_oci_waas_work_request.py new file mode 100644 index 0000000..77c893c --- /dev/null +++ b/test/units/test_oci_waas_work_request.py @@ -0,0 +1,121 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_waas_work_request + +try: + import oci + from oci.waas.models import WorkRequest + from oci.util import to_dict + from oci.exceptions import ServiceError +except ImportError: + raise SkipTest("test_oci_waas_work_request.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def waas_client(mocker): + mock_waas_client = mocker.patch("oci.waas.waas_client.WaasClient") + return mock_waas_client.return_value + + +@pytest.fixture() +def call_with_backoff_patch(mocker): + return mocker.patch.object(oci_utils, "call_with_backoff") + + +@pytest.fixture() +def oci_wait_until_patch(mocker): + return mocker.patch.object(oci, "wait_until") + + +def get_module(**kwargs): + params = dict(work_request_id="ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx") + params.update(kwargs) + module = FakeModule(**params) + return module + + +def get_response(status=200, headers=None, data=None, request=None): + if not headers: + headers = dict() + return oci.Response(status, headers, data, request) + + +def get_work_request(): + return WorkRequest( + id="ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx1", + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + ) + + +def test_cancel_work_request_raises_service_error(waas_client, call_with_backoff_patch): + call_with_backoff_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_work_request.cancel_work_request(waas_client, get_module()) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_cancel_work_request_does_not_call_wait_until_when_wait_set_to_false( + waas_client, call_with_backoff_patch, oci_wait_until_patch +): + module = get_module(wait=False) + work_request = get_work_request() + call_with_backoff_patch.return_value = get_response(data=work_request) + result = oci_waas_work_request.cancel_work_request(waas_client, module) + assert call_with_backoff_patch.call_count == 2 + call_with_backoff_patch.assert_any_call( + waas_client.cancel_work_request, + work_request_id=module.params["work_request_id"], + ) + call_with_backoff_patch.assert_any_call( + waas_client.get_work_request, work_request_id=module.params["work_request_id"] + ) + assert oci_wait_until_patch.call_count == 0 + assert result["changed"] is True + assert result["waas_work_request"] == to_dict(work_request) + + +def test_cancel_work_request_calls_wait_until_when_wait_set_to_true( + waas_client, call_with_backoff_patch, oci_wait_until_patch +): + module = get_module(wait=True) + work_request = get_work_request() + call_with_backoff_patch.return_value = get_response(data=work_request) + oci_wait_until_patch.return_value = get_response(data=work_request) + result = oci_waas_work_request.cancel_work_request(waas_client, module) + assert call_with_backoff_patch.call_count == 2 + call_with_backoff_patch.assert_any_call( + waas_client.cancel_work_request, + work_request_id=module.params["work_request_id"], + ) + call_with_backoff_patch.assert_any_call( + waas_client.get_work_request, work_request_id=module.params["work_request_id"] + ) + assert oci_wait_until_patch.call_count == 1 + assert result["changed"] is True + assert result["waas_work_request"] == to_dict(work_request) diff --git a/test/units/test_oci_waas_work_request_facts.py b/test/units/test_oci_waas_work_request_facts.py new file mode 100644 index 0000000..09c0565 --- /dev/null +++ b/test/units/test_oci_waas_work_request_facts.py @@ -0,0 +1,172 @@ +# Copyright (c) 2019, Oracle and/or its affiliates. +# This software is made available to you under the terms of the GPL 3.0 license or the Apache 2.0 license. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Apache License v2.0 +# See LICENSE.TXT for details. + +import pytest +from nose.plugins.skip import SkipTest +from ansible.module_utils.oracle import oci_utils +from ansible.modules.cloud.oracle import oci_waas_work_request_facts + +try: + import oci + from oci.util import to_dict + from oci.response import Response + from oci.exceptions import ServiceError + from oci.waas.models import WorkRequestSummary +except ImportError: + raise SkipTest("test_oci_waas_work_request_facts.py requires `oci` module") + + +class FakeModule(object): + def __init__(self, **kwargs): + self.params = kwargs + + def fail_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + raise Exception(kwargs["msg"]) + + def exit_json(self, *args, **kwargs): + self.exit_args = args + self.exit_kwargs = kwargs + + +@pytest.fixture() +def waas_client(mocker): + mock_waas_client = mocker.patch("oci.waas.waas_client.WaasClient") + return mock_waas_client.return_value + + +@pytest.fixture() +def list_all_resources_patch(mocker): + return mocker.patch.object(oci_utils, "list_all_resources") + + +@pytest.fixture() +def call_with_backoff_patch(mocker): + return mocker.patch.object(oci_utils, "call_with_backoff") + + +def get_module(with_work_request=False, **kwargs): + if with_work_request: + params = dict(work_request_id="ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx") + else: + params = dict( + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + waas_policy_id="ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx", + ) + params.update(kwargs) + module = FakeModule(**params) + return module + + +def get_work_requests(): + return [ + WorkRequestSummary( + id="ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx1", + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + ), + WorkRequestSummary( + id="ocid1.waasworkrequest.oc1..xxxxxEXAMPLExxxxx2", + compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx", + ), + ] + + +def get_response(status=200, headers=None, data=None, request=None): + if not headers: + headers = dict() + return oci.Response(status, headers, data, request) + + +def test_list_work_requests_raises_service_error(waas_client, list_all_resources_patch): + list_all_resources_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_work_request_facts.list_work_requests(waas_client, get_module()) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_list_work_requests_fails_when_required_attrs_not_present_in_module( + waas_client, list_all_resources_patch +): + module = FakeModule() + with pytest.raises(Exception) as exc_info: + oci_waas_work_request_facts.list_work_requests(waas_client, module) + ex = exc_info.value + assert "required to list work requests" in str(ex) + module = FakeModule(compartment_id="ocid1.compartment.oc1..xxxxxEXAMPLExxxxx") + with pytest.raises(Exception) as exc_info: + oci_waas_work_request_facts.list_work_requests(waas_client, module) + ex = exc_info.value + assert "required to list work requests" in str(ex) + module = FakeModule(waas_policy_id="ocid1.waaspolicy.oc1..xxxxxEXAMPLExxxxx") + with pytest.raises(Exception) as exc_info: + oci_waas_work_request_facts.list_work_requests(waas_client, module) + ex = exc_info.value + assert "required to list work requests" in str(ex) + + +def test_list_work_requests_calls_list_all_resources_with_correct_parameters( + waas_client, list_all_resources_patch +): + module = get_module(sort_by="timeStarted", sort_order="DESC") + list_all_resources_patch.return_value = [] + oci_waas_work_request_facts.list_work_requests(waas_client, module) + list_all_resources_patch.assert_called_once() + list_all_resources_patch.assert_called_with( + waas_client.list_work_requests, + compartment_id=module.params["compartment_id"], + waas_policy_id=module.params["waas_policy_id"], + sort_by="timeStarted", + sort_order="DESC", + ) + + +def test_list_work_requests_calls_get_work_request( + waas_client, list_all_resources_patch, call_with_backoff_patch +): + module = get_module() + work_requests = get_work_requests() + list_all_resources_patch.return_value = work_requests + oci_waas_work_request_facts.list_work_requests(waas_client, module) + list_all_resources_patch.assert_called_once() + assert call_with_backoff_patch.call_count == 2 + call_with_backoff_patch.assert_any_call( + waas_client.get_work_request, work_request_id=work_requests[0].id + ) + call_with_backoff_patch.assert_any_call( + waas_client.get_work_request, work_request_id=work_requests[1].id + ) + + +def test_get_work_request_raises_service_error(waas_client, call_with_backoff_patch): + call_with_backoff_patch.side_effect = ServiceError( + 500, "InternalServerError", dict(), "Internal Server Error" + ) + with pytest.raises(ServiceError) as exc_info: + oci_waas_work_request_facts.get_work_request( + waas_client, get_module(with_work_request=True) + ) + se = exc_info.value + assert se.status == 500 + assert se.code == "InternalServerError" + assert se.message == "Internal Server Error" + + +def test_get_work_request_calls_call_with_backoff_with_correct_parameters( + waas_client, call_with_backoff_patch +): + module = get_module(with_work_request=True) + call_with_backoff_patch.return_value = get_response(data=None) + oci_waas_work_request_facts.get_work_request(waas_client, module) + call_with_backoff_patch.assert_called_once() + call_with_backoff_patch.assert_called_with( + waas_client.get_work_request, work_request_id=module.params["work_request_id"] + )