diff --git a/all.sas b/all.sas index a8cf5ba..491f3a7 100644 --- a/all.sas +++ b/all.sas @@ -16932,14 +16932,22 @@ run; %mend mv_jobwaitfor;/** @file mv_registerclient.sas @brief Register Client and Secret (admin task) - @details When building apps on SAS Viya, an client id and secret is required. - This macro will obtain the Consul Token and use that to call the Web Service. + @details When building apps on SAS Viya, an client id and secret are sometimes + required. In order to generate them, filesystem access to the Consul Token + is needed (it is not enough to be in the SASAdministrator group in SAS + Environment Manager). - more info: https://developer.sas.com/reference/auth/#register - and: - http://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches + If you are registering a lot of clients / secrets, you may find it more + convenient to use the [Viya Token Generator] + (https://sasjs.io/apps/#viya-client-token-generator) (a SASjs Web App to + automate the generation of clients & secrets with various settings). - The default viyaroot location is /opt/sas/viya/config + For further information on clients / secrets, see; + @li https://developer.sas.com/reference/auth/#register + @li https://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches + @li https://cli.sasjs.io/faq/#how-can-i-obtain-a-viya-client-and-secret + + The default viyaroot location is: `/opt/sas/viya/config` Usage: @@ -16964,16 +16972,19 @@ run; ) @param client_id= The client name. Auto generated if blank. - @param client_secret= Client secret Auto generated if client is blank. - @param scopes= list of space-seperated unquoted scopes (default is openid) - @param grant_type= valid values are "password" or "authorization_code" - (unquoted) - @param outds= the dataset to contain the registered client id and secret - @param access_token_validity= The duration of validity of the access token - in seconds. A value of DEFAULT will omit the entry (and use system default) - @param refresh_token_validity= The duration of validity of the refresh token - in seconds. A value of DEFAULT will omit the entry (and use system default) - @param name= A human readable name for the client + @param client_secret= Client secret. Auto generated if client is blank. + @param scopes=(openid) List of space-seperated unquoted scopes + @param grant_type=(authorization_code|refresh_token) Valid values are + "password" or "authorization_code" (unquoted) + @param outds=(mv_registerclient) The dataset to contain the registered client + id and secret + @param access_token_validity=(DEFAULT) The duration of validity of the access + token in seconds. A value of DEFAULT will omit the entry (and use system + default) + @param refresh_token_validity=(DEFAULT) The duration of validity of the + refresh token in seconds. A value of DEFAULT will omit the entry (and use + system default) + @param name= An optional, human readable name for the client @param required_user_groups= A list of group names. If a user does not belong to all the required groups, the user will not be authenticated and no tokens are issued to this client for that user. If this field is not specified, @@ -16982,8 +16993,8 @@ run; apply. Setting this to true will autoapprove all the client scopes. @param use_session= If true, access tokens issued to this client will be associated with an HTTP session and revoked upon logout or time-out. - @param outjson= A dataset containing the lines of JSON submitted. Useful - for debugging. Default= _null_. + @param outjson= (_null_) A dataset containing the lines of JSON submitted. + Useful for debugging. @version VIYA V.03.04 @author Allan Bowe, source: https://github.com/sasjs/core @@ -17020,12 +17031,26 @@ run; options noquotelenmax; /* first, get consul token needed to get client id / secret */ %let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default; +%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token; + + +%mp_abort(iftrue=(%sysfunc(fileexist(&tokloc))=0) + ,mac=&sysmacroname + ,msg=%str(Unable to access the consul token at &tokloc) +) + +%let consul_token=0; data _null_; - infile "%mf_loc(VIYACONFIG)&tokloc/client.token"; + infile "&tokloc"; input token:$64.; call symputx('consul_token',token); run; +%mp_abort(iftrue=("&consul_token"="0") + ,mac=&sysmacroname + ,msg=%str(Unable to source the consul token from &tokloc) +) + %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); @@ -17172,7 +17197,7 @@ filename &fname2 clear; filename &fname3 clear; libname &libref clear; -%mend; +%mend mv_registerclient; /** @file mv_tokenauth.sas @brief Get initial Refresh and Access Tokens diff --git a/tests/viya/mv_registerclient.test.1.sas b/tests/viya/mv_registerclient.test.1.sas new file mode 100644 index 0000000..ae55ef4 --- /dev/null +++ b/tests/viya/mv_registerclient.test.1.sas @@ -0,0 +1,36 @@ +/** + + @file + @brief Testing mv_registerclient.sas macro + @details Tests for successful registration. For this to work, the test + account must be an admin. +​ +

SAS Macros

+ @li mf_getuniquename.sas + @li mp_assertcolvals.sas + @li mv_registerclient.sas + +**/ + +/** + * Test Case 1 + */ + +%let id=%mf_getuniquename(); +%let sec=%mf_getuniquename(); +%mv_registerclient(client_id=&id,client_secret=&sec, outds=testds) + +data work.checkds; + id="&id"; + sec="&sec"; +run; +%mp_assertcolvals(work.testds.client_id, + checkvals=work.checkds.id, + desc=Checking client id was created + test=ALLVALS +) +%mp_assertcolvals(work.testds.client_secret, + checkvals=work.checkds.sec, + desc=Checking client secret was created + test=ALLVALS +) \ No newline at end of file diff --git a/tests/viya/mv_registerclient.test.2.sas b/tests/viya/mv_registerclient.test.2.sas new file mode 100644 index 0000000..2f2d561 --- /dev/null +++ b/tests/viya/mv_registerclient.test.2.sas @@ -0,0 +1,43 @@ +/** + + @file + @brief Testing mv_registerclient.sas macro + @details Tests for unsuccessful registration. To do this, overrides are + applied for the mf_loc.sas and mp_abort.sas macros. +​ +

SAS Macros

+ @li mp_assert.sas + @li mv_registerclient.sas + +**/ + +/** + * Test Case + */ + +%macro mf_loc(param); + /does/not/exist +%mend mf_loc; + +%macro mp_abort(iftrue=,mac=mp_abort.sas, type=, msg=); + %if not(%eval(%unquote(&iftrue))) %then %return; + %put %substr(&msg,1,16); + %mp_assert( + iftrue=("%substr(&msg,1,16)"="Unable to access"), + desc=Check that abort happens when consul token is unavailable + ) + %webout(OPEN) + %webout(OBJ, TEST_RESULTS) + %webout(CLOSE) + %let syscc=0; + data _null_; + abort cancel nolist; + run; +%mend mp_abort; + +%mv_registerclient( outds=testds) + +%mp_assert( + iftrue=(0=1), + desc=Check that abort happens when consul token is unavailable +) \ No newline at end of file diff --git a/viya/mv_registerclient.sas b/viya/mv_registerclient.sas index a1fca07..b248a57 100644 --- a/viya/mv_registerclient.sas +++ b/viya/mv_registerclient.sas @@ -1,14 +1,22 @@ /** @file mv_registerclient.sas @brief Register Client and Secret (admin task) - @details When building apps on SAS Viya, an client id and secret is required. - This macro will obtain the Consul Token and use that to call the Web Service. + @details When building apps on SAS Viya, an client id and secret are sometimes + required. In order to generate them, filesystem access to the Consul Token + is needed (it is not enough to be in the SASAdministrator group in SAS + Environment Manager). - more info: https://developer.sas.com/reference/auth/#register - and: - http://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches + If you are registering a lot of clients / secrets, you may find it more + convenient to use the [Viya Token Generator] + (https://sasjs.io/apps/#viya-client-token-generator) (a SASjs Web App to + automate the generation of clients & secrets with various settings). - The default viyaroot location is /opt/sas/viya/config + For further information on clients / secrets, see; + @li https://developer.sas.com/reference/auth/#register + @li https://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches + @li https://cli.sasjs.io/faq/#how-can-i-obtain-a-viya-client-and-secret + + The default viyaroot location is: `/opt/sas/viya/config` Usage: @@ -33,16 +41,19 @@ ) @param client_id= The client name. Auto generated if blank. - @param client_secret= Client secret Auto generated if client is blank. - @param scopes= list of space-seperated unquoted scopes (default is openid) - @param grant_type= valid values are "password" or "authorization_code" - (unquoted) - @param outds= the dataset to contain the registered client id and secret - @param access_token_validity= The duration of validity of the access token - in seconds. A value of DEFAULT will omit the entry (and use system default) - @param refresh_token_validity= The duration of validity of the refresh token - in seconds. A value of DEFAULT will omit the entry (and use system default) - @param name= A human readable name for the client + @param client_secret= Client secret. Auto generated if client is blank. + @param scopes=(openid) List of space-seperated unquoted scopes + @param grant_type=(authorization_code|refresh_token) Valid values are + "password" or "authorization_code" (unquoted) + @param outds=(mv_registerclient) The dataset to contain the registered client + id and secret + @param access_token_validity=(DEFAULT) The duration of validity of the access + token in seconds. A value of DEFAULT will omit the entry (and use system + default) + @param refresh_token_validity=(DEFAULT) The duration of validity of the + refresh token in seconds. A value of DEFAULT will omit the entry (and use + system default) + @param name= An optional, human readable name for the client @param required_user_groups= A list of group names. If a user does not belong to all the required groups, the user will not be authenticated and no tokens are issued to this client for that user. If this field is not specified, @@ -51,8 +62,8 @@ apply. Setting this to true will autoapprove all the client scopes. @param use_session= If true, access tokens issued to this client will be associated with an HTTP session and revoked upon logout or time-out. - @param outjson= A dataset containing the lines of JSON submitted. Useful - for debugging. Default= _null_. + @param outjson= (_null_) A dataset containing the lines of JSON submitted. + Useful for debugging. @version VIYA V.03.04 @author Allan Bowe, source: https://github.com/sasjs/core @@ -89,12 +100,26 @@ options noquotelenmax; /* first, get consul token needed to get client id / secret */ %let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default; +%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token; + + +%mp_abort(iftrue=(%sysfunc(fileexist(&tokloc))=0) + ,mac=&sysmacroname + ,msg=%str(Unable to access the consul token at &tokloc) +) + +%let consul_token=0; data _null_; - infile "%mf_loc(VIYACONFIG)&tokloc/client.token"; + infile "&tokloc"; input token:$64.; call symputx('consul_token',token); run; +%mp_abort(iftrue=("&consul_token"="0") + ,mac=&sysmacroname + ,msg=%str(Unable to source the consul token from &tokloc) +) + %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); @@ -241,4 +266,4 @@ filename &fname2 clear; filename &fname3 clear; libname &libref clear; -%mend; +%mend mv_registerclient;