Script files
A script defines interaction between the connector and the database or OS/400 target.
Scripts for scripted connectors are stored in text files on the Bravura Security Fabric server. They are conventionally named with a .sql file name extension, although there is no technical requirement for the extension. You can write custom scripts which must be added in the <Program Files path>\Bravura Security\Bravura Security Fabric\<instance>\ script\ directory. Official, shipped scripts are included in the agent directory, and use a scripted platform definition file (.con) to call one of the binary agents. The official scripts are designed to work "out of the box", but can be modified to suit your requirements.
The following topics describe how to write the SQL configuration script.
Comments
Scripts may contain comments. Any line of text that begins with a hash mark (#) is ignored by the connector.
# This is a comment, these lines will # not be executed.
KVGroups for SQL scripted connectors
Write scripts for scripted connectors using KVGroups .
Each script includes a main or outer KVGroup that acts as a container for the script. The value of the key for the main KVGroup indicates the protocol that the connector will expect.
Top-level KVGroup
The value in the name of the main KVGroup indicates the version of the protocol. This version of the scripted connectors requires the value of the key to be "m-tech:agents:sqlscript" and the name to be "1.1":
"m-tech:agents:sqlscript" "1.1" = { "operation" "<operation name>" = { ... } # 0 or more }
Each script file must only contain one main KVGroup.
Operation KVGroup
The main KVGroup contains a set of inner KVGroups. These KVGroups have a key "operation" and a name <operation name> that corresponds to the actual operation name (see Supported operations for a list of supported operations).
The operation KVGroups define the implementation details for the operation of the connector; this includes: connection information, commands to issue, and return values. Operation KVGroups are defined as follows:
"operation" "<operation name>" = { "login" = "<login id>" "password" = "<login password>" # See Connection credentials "usetransaction" = "[true|false]" # Optional; only for SQL Server # When true if any errors occur during the SQL sequence then the # successful statements are not committed (default = false). "proceedblocks" = "[true|false]" # When true if any errors occur while running one block SQL, # agent can proceed to run following SQL blocks (default = false). "filter" "" = { ... } # Optional; This provides calls to external programs # See Filter KVGroup "return" "" = } # Optional; This binds information returned for respective # operations. See Return KVGroup "block" "<sequence number:1..N>" = { ... } # Mandatory; A minimum of one block is required per operation # See Block KVGroup }
If an operation requires the return of attribute information, a "returns" KVGroup is required.
If an operation requires a return value to indicate success or failure result, the last block must return a value using a SELECT statement.
Connection credentials
Each operation KVGroup require credentials used when connecting to the database.
This information is defined using the "login" and "password" key-value pairs. For example:
"login" = "<target administrator ID>" "password" = "<password>"
Typically the value for these two keys will leverage the one of two built-in variables. Alternatively, hard-coded values can be used but not recommended.
Connecting with built-in variables as target system administrator:
"login" = "%k:_adminID%" "password" = "%k:_adminPW"
Connecting with built-in variables as the end user (for verify operations):
"login" = "%k:_acctID%" "password" = "%k:_oldPW"
Filter KVGroup
This optional KVGroup is used to call an external program. The executed program must be in the \<instance>\plugin\ directory. This allows you to translate or generate a value for use in the SQL statements. This often is required to take a password and apply a hash algorithm.
The filter KVGroup must be in the following format:
"filter" "" = { "command" = "<program name>" # Mandatory "input" = "<what to send to stdin>" # Optional "args" = "<command line args>" # Optional "outputvar" = "<name of variable to output to>" # Mandatory }
The value of "command" is executed and uses any other values set, such as "input" or "args". The values for "input" or "args" can accept substitutions of existing variables. The "outputvar" value is a variable that is available when binding.
For example:
"filter" "" = { "command" = "pwdhash.exe" "args" = "hash -encalg hex -hashalg md5 -password %k:_newPW%" "outputvar" = "hashedPW" }
Return KVGroup
Each operation that returns attributes (such as list operations), requires a return KVGroup. This binds columns returned from the SQL statement to the attributes listed in the return KVGroup.
The return KVGroup as the following form:
"returns" "" = { "column" = "<attribute name>" ... }
For example, for listusers:
"returns" "" = { "column" = "LONGID" "column" = "SHORTID" "column" = "FULLNAME" "column" = "FIRST_NAME" "column" = "LAST_NAME" }
The columns must appear in the same order as the attributes in your "sql" select command. For each attribute, one or more columns are required and cannot be modified. For example, in the listusers example above, the first three columns are special:
The first column is always treated as the LONGID, regardless of the name set in the KVGroup.
The second column is always treated as the SHORTID, regardless of the name set in the KVGroup.
The third column is always treated as the FULLNAME, regardless of the name set in the KVGroup.
Note
Although the names of the first three columns are ignored, it is recommended that you specify them for legibility.
If there are only two columns, then FULLNAME is not set, but LONGID and SHORTID are set. If there is only one column, then only LONGID is set.
All columns after the third column are treated as account attributes, and they use the same attribute names as they appear in the KVGroup.
For every column being returned, a corresponding account attribute needs to be created in the administrative web interface for that target. The case of each attribute name in this script file must match the case defined in the Bravura Security Fabric account attributes screen.
Block KVGroup
Each operation requires a minimum of one block. Each block must contain one or more "sql" key-value pair. Each block binds the variables used for each SQL statement. The format of the block KVGroup is as follows:
"block" "<sequence number:1..N>" = { "bind" "<sequence number:1..N>" = { ... } # 0 or more; required for each variable bound in the SQL statement "sql" = "<SQL statement>" # Mandatory; this is the SQL statement that # is executed }
Columns are associated into account attributes via the "return" block; column names in "Select" SQL statements are irrelevant, but the order is important because it must match the order of the return block.
Bind KVGroup
There are three ways of using variables in SQL statements. Some kinds are limited to the specific back end database. These types are as follows:
Binding by name: The Oracle database connector only supports binding by name.
Binding by position: All other database connectors support binding by position.
Substitution: The connector replaces the value within the SQL statements verbatim.
Note
Bound variables do not work for IBM OS/400 Server Script targets, DB2, and Sybase ASE. All variables must be specified using the %k:VARNAME% syntax directly in the command.
Binding by name has the following form:
"block" "1" = { "bind" "1" = { "name" = "firstname" # name used within SQL statement "value" = "%k:FIRST_NAME%" # where FIRST_NAME is the request attribute or output # variable from a filter kvg. } "bind" "2" = { "name" = "appuserid" "value" = "%k:_acctID%" # where _acctID is a built-in variable passed to # the connector } "sql" = "update people set firstname= :firstname where appuserid = :appuserid" }
Binding by position has the following form:
"block" "1" = { "bind" "1" = { "value" = "%k:FIRST_NAME%" # where FIRST_NAME is the request attribute or output # variable from a filter kvg. } "bind" "2" = { "value" = "%k:_acctID%" # where _acctID is a built-in variable passed to # the connector } "sql" = "update people set firstname = ? where appuserid = ?" }
Substitution requires no bind KVGroup as the value is replaced in the SQL statement as is in the variable. Substitution of variable is in the following form:
"block" "1" = { "sql" = "update people set firstname = '%k:FIRST_NAME%' where appuserid = '%k:_acctID%'" }
Binding of variables is only valid in the scope of each block. Multiple blocks under the same operation required rebinding in order to use variables.
Replacement strings
A number of input parameters can be used as replacement and bind strings within your SQL queries. These strings can be replaced entirely or a substring of the replacement can be used. The following is a list of valid replacement formats:
Format | Description |
---|---|
%k:key% | replace with the entire key |
%k:start:key% | replace starting at position "start" to the end of the key |
%k::end:key% | replace starting at the beginning up into position end. |
%k:start:end:key% | replace with the substring up to and including start/end. |
The table below lists the built-in variables accessible in all operations of the scripted connectors. Depending on the operation, the value of these built-in variables may be blank.
Key | Description |
---|---|
_adminID | the target system administrator ID |
_adminPW | the target system administrator password |
_address | the target address |
_instance | the database instance name configured as part of the target address |
_userID | the user’s profile ID |
_acctID | the account’s long ID |
_groupID | the group ID |
_oldPW | the account’s old password (if known) |
_newPW | the account’s new password |
_hostID | the target ID |
_modelUID | the template account ID (for Bravura Security Fabric ) |
_containerdn | the account’s container dn (distinguished name). The containerdn variable is only available for the movecontext operation. |
Address attributes
You can define additional replacement variables by adding target system address attributes. This is useful when creating a scripted target system with a scripted platform definition file.
The AddressAttr operation is an exception to the rules described in this chapter, in that it does not include credential and block keys. This operation supports extending the target system address wizard by adding address attributes to the configuration script file in the following form:
"operation" "AddressAttrs" = { "<attributeName>" "" = { "defaultValue" = "<defaultValue>" "required" = "<true|false>" "type" = "<String|Boolean|Integer|etc.>" "languageTag" = "!!!<languageTag>" } "sampleAttribute" "" = { "defaultValue" = "sampleValue" "required" = "false" "type" = "String" "languageTag" = "!!!sampleAttrDescription" } }
Supported operations
The following operations can be defined in your script. If you omit an operation, the connector will report that it is unsupported.
Password verification operations
verify
Purpose: Checks if a given password is the correct, current password for an account. If the application supports the concept of intruder lockout and the verification fails, the intruder lockout counter is incremented.
Returns: Returns 1 for success and 0 for failure.
adminverify
Purpose: Checks if a given password is the correct, current password for an account without triggering an intruder lockout if the password is not correct.
Returns: Returns 1 for success and 0 for failure.
Notes: If the application does not support the concept of intruder lockout, then this operation should not be used.
Password reset operations
change
Purpose: Changes the password for an account, from a known current value to a desired new value. If the application supports the concept of intruder lockout, then the intruder lockout counter is cleared and the account unlocked. If the application supports the concept of password expiry, then the expiry date is set according to the expiry policy of the application.
Returns: Nothing.
Notes: This operation differs from the reset operation in that this operation requires the user’s existing password to be provided during the reset process.
reset
Purpose: Administratively resets an account’s password to a new value. If the application supports the concept of intruder lockout, then the intruder lockout counter is cleared and the account unlocked. If the application supports the concept of password expiry, then the expiry date is set according to the expiry policy of the application. Disabled accounts will remain disabled.
Returns: Nothing.
Notes: This operation differs from the change operation in that this operation does not require the user’s existing password.
resetexpirepw
Purpose: Administratively resets an account’s password to a new value and expires the account’s new password, so that the user is forced to change his password the next time he logs in.
Returns: Nothing.
Notes: If the application does not support the concept of password expiry, then this operation should not be implemented.
verifyreset
Purpose: Verifies if the account’s password matches the new password, and if the verification fails, administratively sets it to the new password. If the verification succeeds, then the reset is not necessary, and the operation returns success.
Returns: Nothing.
Notes: This special reset operation is generally only used by the Password Manager service (
idpm
) to improve queue processing performance.updatesubscriber
Purpose: Updates subscriber attributes, typically password.
Returns: Nothing.
Notes: This operation is similar to the reset operation except that in addition to the reset password replacement string, the following replacement strings must be provided:
%k_resourceType%
the same resource types provided in listsubscribers.%k_resourceURI%
the unique URI of the subscriber to be updated. This is the same as the uri column in listsubscribers.Warning
Functions which reset or verify passwords in scripts used by Bravura Privilege for password randomization must always report the result of the reset or verification accurately. Inaccurate status information may result in checked out passwords not working; additionally, if the credential used to manage the target system is being randomized, Bravura Privilege may invalidate its own managed system credential when an erroneous status is returned. Do not assume scripted password changes are always successful; always check return codes.
Account enable/disable operations
When an account is disabled, a user cannot log in using that account even if the user knows the correct password for the account.
If the application supports the concept of account enable/disable status, then all three of the following operations should be implemented. If the application does not support this concept, then none of the operations should be implemented.
Most applications differentiate between an enabled/disabled state and an unlocked/locked state. If your application does not differentiate between these two concepts, you can choose to implement either set or both sets of operations with the same statements.
isenabled
Purpose: Checks if an account is enabled.
Returns: Returns 1 if the account is enabled and 0 if it is disabled.
enable
Purpose: Enables an account.
Returns: Nothing.
disable
Purpose: Disables an account.
Returns: Nothing.
Intruder lock-out operations
When an account is locked out, the user cannot log in using the account even if the user knows the correct password for the account.
If the application supports the concept of intruder lock-out status, then all of the following operations should be implemented. If the application does not support this concept, then none of the operations should be implemented.
Most applications differentiate between an enabled/disabled state and an unlocked/locked state. If your application does not differentiate between these two concepts, you can either choose to implement either set or both sets of operations with the same statements (if applicable).
islocked
Purpose: Checks if an account is locked.
Returns: Returns 1 if the account is locked out and 0 if the account is not locked out.
lock
Purpose: Locks an account (sets the intruder lockout).
Returns: Nothing.
unlock
Purpose: Unlocks an account (clears the intruder lockout).
Returns: Nothing.
Expiry operations
There are two types of expiry relating to accounts: password expiry and account expiry. When the password is expired, the application will force the user to change it during his next log in after he has successfully authenticated using his current password. When an account is expired, it is no longer usable, and the user cannot log in using the account even if he knows the correct password for the account.
If the application supports the concept of either password expiry or account expiry, then all of the related operations should be implemented. If the application does not support either concept, then none of the related operations should be implemented.
Most applications differentiate between password expiry and account expiry. If your application does not differentiate between the two concepts, you can choose to implement either set or both sets of operations with the same statements (if applicable).
isexpiredpw
Purpose: Checks if an account’s password is expired.
Returns: Returns 1 if the condition is true and 0 if it is false.
expirepw
Purpose: Expires an account’s password.
Returns: Nothing.
unexpirepw
Purpose: Unexpires an account’s password.
Returns: Nothing.
isacctexpired
Purpose: Checks if an account is expired.
Returns: Returns 1 if the condition is true and 0 if it is false.
expireacct
Purpose: Expires an account.
Returns: Nothing.
unexpireacct
Purpose: Unexpires an account.
Returns: Nothing.
Listing operations
All of the listing operations described below are expected to return one or more rows of data. If an operation returns no rows, then the operation is considered to have failed. See Return KVGroup for information about the return KVGroup.
listusers
Purpose: Lists accounts on the target system, and the attributes for each account.
Returns: Returns a row for each user, with the first column being the user’s long ID, the second being the user’s short ID, and the third being the user’s full name, and the rest being attributes. Nothing returned indicates failure.
Notes: This operation requires a "returns" KVGroup that identifies attribute names. The "returns" KVGroup must include the LONGID, SHORTID, and FULLNAME attributes as the first three attribute names.
listgroups
Purpose: Lists groups.
Returns: Returns a row for each group on the target. The first column is the long ID of the group, the second column is the group description, the third column is the long ID of the group owner, the fourth column is the short ID of the group, and the fifth column is a flag indicating if the group owner is a group, "1" or "true" or "t" indicates it is a group, otherwise it is a user. Nothing returned indicates failure.
Notes: This operation is a sequenced operation that is followed by the invocation of the listmembers operation. This operation must only return a maximum of one owner for each group.
listmembers
Purpose: Lists members of a managed group.
Returns: Returns a row for each user that is a member of the group. The first column returned is the long ID of the user that is a member, and the second column indicates if the member is a user or a group, "1" or "true" or "t" indicates the member is a group, otherwise it is a user. Nothing returned indicates failure.
Notes: This operation is a sequenced operation that is preceded by the invocation of the listgroups operation.
listcomputers
Purpose: Lists computer objects on a target system.
Returns: Returns a row for each computer object on the target system. The first four columns must be:
id Univerally unique identifier for this computer
name Descriptive name for this computer
restype the resource type, can be accessed using %k_resourceType% , or a column from real table
disabled Flag to indicate if this computer is disabled (0=false, 1=true)
You can add columns to specify any computer attributes you want to list, for example:
"column" = "ip" "column" = "os" "column" = "location"
Notes: A replacement string should be passed into the operation, %k_resourceType% , which will be either "ls_compwkstn" or "ls_compsvr" to distinguish between listing workstations and server computers.
listsubscribers
Purpose: Lists subscriber accounts on a target system.
Returns: Returns a row for each subscriber on the target system. The first seven columns must be:
id Universally unique identifier for this account (optional - if empty will auto-generate to longid+targetid)
uri Unique identifier for the subscriber
restype the resource type, can be accessed using %k_resourceType% , or a column from real table
disabled Flag to indicate if this account is disabled (0=false, 1=true)
acctid Account name as seen by the subscriber using it
longid Long identifier for the account; for example FQDN
shortid Short identifier for the account; for example CN
You can add columns to specify any subscriber attributes you want to list, for example:
"column" = "sid" "column" = "domain" "column" = "Comment" "column" = "islocal"
Notes: A replacement string should be passed into the operation,
%k_resourceType%
, which will be one of:ls_taskacct Task subscriber
ls_iisacct IIS subscriber
ls_comacct DCOM/COM+ subscriber
ls_scmacct Service subscriber
ls_cusacct User defined subscriber
ls_admmember Administrative group member
Account creation operations
The typical behavior of all built-in connectors is to copy a template account, and then update the attributes of the copy. Scripted connectors are capable of creating accounts using that technique, but they can also bypass the use of template accounts, simply by not including the checktemplate operation in the script.
When the account creation operation is expected to use a template, and the group membership of the template needs to be included during the create operation, then checktemplate should return the group long IDs of the template in an attribute, which the create operation can then parse and add to the new account.
checktemplate
Purpose: Checks if the template to be copied exists on the target system and returns attributes of the template account if it exists.
Returns: Returns a single row and a column for each attribute of the template account. The first three columns returned must be the long ID, short ID, and the full name of the template account. After that, other columns can be returned for other attributes. Nothing returned indicates failure.
Notes: This operation is a sequenced operation that precedes the execution of the create operation. This operation requires a "returns" KVGroup that identifies attribute names. The "returns" KVGroup must include the LONGID, SHORTID, and FULLNAME attributes as the first two attribute names.
create
Purpose: Creates a new account on the target system. This operation creates the account (possibly using a template for some attribute values), then sets other attribute values – including the password for the new account.
Returns: Nothing.
Notes: This operation is a sequenced operation that first attempts to execute the checktemplate operation.
usergroups
Purpose: List group membership of an account.
Returns: Returns a row for each group membership of the user. Each row must be the long id of the group. Nothing returned indicates failure.
Notes: This operation is a sequenced operation that is called after the create operation.
Account delete operations
The typical behavior of all built-in connectors is to first ensure that the account being deleted exists. For scripted connectors, this is accomplished by the use of the checkuser operation.
delete
Purpose: Deletes an existing account on the target system. The typical behavior is to first ensure that the account being deleted exists.
Returns: Nothing.
Account modification operations
The following operations fall into the category of modification, because they are all used to modify an existing account’s properties (attributes, group membership, long ID, or container).
If this application requires group operations, then both groupuseradd and groupuserdelete operations must be implemented.
update
Purpose: Updates attributes for an existing account.
Returns: Nothing.
Notes: This operation is a sequenced operation that first executes the checkuser operation.
groupuseradd
Purpose: Adds an account to a group.
Returns: Nothing.
groupuserdelete
Purpose: Removes an account from a group.
Returns: Nothing.
Group provisioning operations
If this application requires group provisioning operations, then both the groupcreate and groupdelete operations must be implemented.
groupcreate
Purpose: Creates the specified group.
Returns: Nothing.
groupdelete
Purpose: Deletes the specified group.
Returns: Nothing.
Other operations
The userattributes operation is very similar to the checktemplate operation.
checkuser
Purpose: Checks if the account exists on the target system, and if it exists, returns the attributes of the account.
Returns: Returns a single row and a column for each attribute of the account. The first three columns returned must be the long ID, short ID, and full name. After that, other columns can be returned for other attributes (groups should be returned in a single attribute). Nothing returned indicates failure.
Notes: This operation is a sequenced operation that is called by the delete, update, and userattributes operations. This operation requires a "returns" KVGroup that identifies attribute names. The "returns" KVGroup must include the LONGID and SHORTID attributes as the first two attribute names. Any custom attribute that is defined must be returned using checkuser. This operation should be called after the create operation.
userattributes
Purpose: Lists attributes for a specified account.
Returns: Returns single row and a column for each attribute of the account. The first three columns returned must be the long ID, short ID, and fullname. After that, other columns can be returned for other attributes. Nothing returned indicates failure.
Notes: This operation is a sequenced operation that first calls the checkuser operation to ensure the account exists. This operation requires a "returns" KVGroup that identifies attribute names. The "returns" KVGroup must include the LONGID, SHORTID and FULLNAME attributes as the first three attribute names.
Custom operations
You can define custom operations in the database script file with prefix custom_; for example:
operation "custom_customop" = { "outputType" = "xxx" }
The "outputType" can be defined in three types:
"outputType" = "none"
– no data will return"
outputType" = "single"
– single row of data will return in KVGroup output"outputType" = "multiple"
– multiple rows of data will return and will be written to file specified in "customfilename" in agent input. "customfilename" is required in this type, and the operation will fail without providing the file.