繁体   English   中英

SAS中的ODBC密码安全性

[英]ODBC Password Security in SAS

我们希望从SAS代码中删除ODBC连接字符串中的硬编码密码,并防止任何密码出现在SAS日志文件中。

似乎有很多白皮书讨论如何解决这个问题,但我要么发现问题,要么无法让它们发挥作用。

每次提示用户使用PW都不是一个可行的选择。 此外,将密码存储在宏变量中是一种可接受的方法,只要您有办法在打开MACROGEN和SYMBOLGEN选项时将其禁止打印到日志中。

ATTEMPT 1 - 编码链接到白皮书

proc pwencode in='mypassword' method=sasenc;
run;

得到:

{sasenc}ACFD24061BF77D7D5362EE7C2D00D08B

如果我用我的代码中的编码值替换我的明文密码,那么ODBC passthrough语句运行正常。

proc sql noprint;
  connect to odbc as remote (datasrc=cmg_report user=myuser password='{sasenc}68B279564BD2695538CDCDB301E8A357563480B0');
  create table sqlo as 
  select *
  from connection to remote
  (
  select top 1 * from application
  )
  ;
  disconnect from remote;
quit;

并且日志使用XXXXXXXs正确地屏蔽了这些值。

961  proc sql noprint;
962    connect to odbc as remote (datasrc=cmg_report user=&user_cmg password=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX);
963    create table sqlo as
964    select *
965    from connection to remote
966    (
967    select top 1 * from application
968    )
969    ;
971  quit;
NOTE: Table WORK.SQLO created, with 1 rows and 29 columns.
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.34 seconds
      cpu time            0.01 seconds

上述方法的问题在于,如果有人可以访问代码,他们可以使用加密密码登录,而无需知道明文密码。 因此,虽然它隐藏了实际的密码但它不提供安全性。 对我来说似乎有点傻或者我错过了什么? 编辑:如果您的ODBC密码碰巧在其他地方使用,这提供了一些安全性,但这是关于它。

ATTEMPT 2 - 使用SYMGET链接到白皮书

这个问题是我根本无法让所描述的技术在SAS中运行。 我在XP上运行SAS 9.2,尝试连接到SQL Server数据库。

%let my_password = password;

proc sql noprint;
  connect to odbc (dsn=cmg_report uid=myuser pwd=symget('my_password'));
  create table sqlo as 
  select *
  from connection to remote
  (
  select top 1 * from application
  )
  ;
quit;

我收到以下消息说登录失败:

1034      proc sql noprint;
1035        connect to odbc (dsn=cmg_report uid=myuser pwd=XXXXXX('my_password'));

ERROR: CLI error trying to establish connection: [Microsoft][SQL Server Native Client 10.0][SQL
Server]Login failed for user 'myuser'.

看起来它试图使用“symget”作为实际密码(因为它已在日志中被屏蔽)。 本白皮书中有一些回复说要将symget包装在%sysfunc调用中,但symget()函数是SAS在%sysfunc调用中不允许的少数函数之一,所以我看不出这是怎么回事。

任何其他提示/建议/想法将不胜感激。

谢谢

编辑:如果有一种技术可以使用options symbolgen macrogen打开,那将是特别好的。

Rob,我们遇到了类似的问题,并提出了一种不同的方法,允许我们的所有团队成员运行相同的程序,而不会将我们的id /密码存储在程序中。 它要求每个团队成员都有一个SAS可以访问的安全存储的文本文件(除了所有者之外没有权限)。

以下是ID / PW文件内容的示例:

machine odbc login XX_odbc_id_XX password XXodbc_pw_XX
machine oracle login XX_oracle_id_XX password XX_oracle_pw_XX

我们在UNIX服务器上运行,因此我们存储锁定在主目录中的单个id / pw文件,因此没有其他人可以访问它,在这种情况下它被命名为“.netrc”。 这个线程末尾的宏应该存储在某个地方,然后程序将如下所示:

%let id_pw_text_file = ~/.netrc;

%ODBC_Acct;

proc sql;
   %ODBC_Connect
   create table sqlo as
      select * from connection to odbc
      (
          /*  [ Insert ODBC query here ]  */ 
      );
   %ODBC_Disconnect
   quit;
run;

我尝试修改宏以在您的环境中工作并删除大量特定于我们系统的代码,但显然我无法对其进行测试以确保其有效。 如果您有问题,请告诉我,我会尽力帮助解决问题。 希望这可以帮助。

/*********************************************************************
*  Name:  ODBC_Acct                                                  *
*  Desc:  Set global macro vars containing a users ODBC username     *
*         and password. Retrieves this information from a users      *
*         specific ID/PW file.                                       *
*********************************************************************/
%macro ODBC_Acct( mprint );
   %local __mprint __symbolgen __mlogic;
   %if ( %length( &mprint ) = 0 ) %then %let mprint = NO;
   %if ( %upcase( &mprint ) = NO ) %then %do;
      %let __mprint = %sysfunc( getoption( mprint ));
      %let __symbolgen = %sysfunc( getoption( symbolgen ));
      %let __mlogic = %sysfunc( getoption( mlogic ));
      options nomprint nosymbolgen nomlogic;
   %end;
   %global  odbc_user  odbc_pw;
   %Get_ID_PW( &id_pw_text_file , odbc , odbc_user , odbc_pw )
   %if ( %upcase(&__mprint) ne NOMPRINT ) %then %do;
      options &__mprint &__symbolgen &__mlogic;
   %end;
%mend;

/*********************************************************************
*  Name:  ODBC_Connect, ODBC_Disconnect                              *
*  Desc:  Returns SAS/Access connect or disconnect statements        *
*         for accessing ODBC.                                        *
*********************************************************************/
%macro ODBC_Connect( mprint=no );
   %local __mprint __symbolgen;
   %if ( %upcase(&mprint) = NO ) %then %do;
      %let __mprint = %sysfunc( getoption( mprint ));
      %let __symbolgen = %sysfunc( getoption( symbolgen ));
      options nomprint nosymbolgen;
   %end;
   connect to odbc as remote (
      datasrc=cmg_report
          user = "&odbc_user"
      password = "&odbc_pw"
      );
   %if ( %upcase(&__mprint) ne NOMPRINT ) %then %do;
      options &__mprint &__symbolgen;
   %end;
%mend;
%macro ODBC_Disconnect;
   disconnect from odbc;
%mend;

/*******************************************************************************
*  Name:  GetID_PW                                                             *
*  Desc:  Get loginid and password from a secured file                         *
*------------------------------------------------------------------------------*
*  Arguments:                                                                  *
*    1st   Required. Source file containing IDs and passwords.                 *
*    2nd   Required. Host id.                                                  *
*    3rd   Required. Specify the macro variable to put the loginid.            *
*    4th   Required. Specify the macro variable to put the password.           *
*------------------------------------------------------------------------------*
*******************************************************************************/
%macro Get_ID_PW( source , rhost , usrvar , pw_var );
   %let source_file = &source
   %if ( %sysfunc( fileexist( &source_file ) ) ) %then %do;
      %let rc  = %sysfunc( filename( dummy , &source_file ) );
      %let fid = %sysfunc( fopen( &dummy ) );
      %do %while( %sysfunc( fread( &fid ) ) = 0 );
         %let rc = %sysfunc( fget( &fid , inrec , 500 ) );
         %let machine = %scan( &inrec , 2 , %str( ) );
         %if ( %upcase( &machine ) = %upcase( &rhost ) ) %then %do;
            %let &usrvar = %scan( &inrec , 4 , %str( ) );
            %let &pw_var = %scan( &inrec , 6 , %str( ) );
            %goto Break;
         %end;
      %end;
      %Break: %*;
      %let rc = %sysfunc( fclose( &fid ) );
      %let rc = %sysfunc( filename( dummy ) );
   %end;
   %else %do;
       %put ::: ID/PW file "&source_file" not found;
   %end;
%mend;

所以我也联系了SAS,看看他们对这类问题的建议是什么,这是他们(及时一如既往)的回应。 不幸的是,看起来他们无法在不禁用symbolgen的情况下实现这一点:

为了防止密码被硬编码到SAS程序中,或者出现在SAS日志中,建议使用以下方法:

1)最安全的选项是使用所需的SAS / Access引擎发出LIBNAME语句,并指定DBPROMPT = YES。 这将在SAS代码运行时提示您输入数据库的连接信息,以便您的程序中不会存储任何连接信息。

但是,由于这在运行作业时需要一些手动交互,因此在您的情况下可能不可行。

2)数据库连接信息可以存储在SAS注册表中,连接所需的密码将被加密。 要进行此设置,请以交互方式运行SAS,然后在“资源管理器”窗口中突出显示“库”。 从pmenus中,选择File-New。 在“名称”框中输入要用于数据库连接的libref,然后从下拉菜单中选择正在使用的数据库引擎。 选择引擎后,您将看到一个允许您输入用户名,密码,路径和选项的窗口。 填写您的连接信息,然后单击右上角的小按钮,指示“启动时启用”。 此方法将您的连接信息存储在SAS注册表中,并在您启动SAS时自动连接。 在批处理模式下运行SAS时,必须在调用时指定-startlib,以便分配库。 您的密码将作为加密值显示在SAS日志中。

3)如果运行PROC SQL Pass-Through,您可以在SAS调用时通过-sysparm选项将密码传递给SAS,并使用通常编码密码的&sysparm SAS宏变量。 一个例子如下:

sas -nodms -sysparm mypassword

1? PROC SQL; 2? 连接到ORACLE(user = scott password =“&sysparm”);

请注意,如果宏选项MPRINT和/或SYMBOLGEN生效,则解析的宏变量将显示在SAS日志中,因此,您的密码将以纯文本形式显示在SAS日志中。 NOMPRINT和NOSYMBOLGEN是默认设置。

4)此外,如果运行PROC SQL Pass-Through,您可以将CONNECT语句存储在受操作系统权限保护的文件中,这样只有您具有读取权限,然后使用%INCLUDE语句包含CONNECT语句。 一个例子如下:

sas -nodms

1? 选项NOSOURCE2; 2? PROC SQL; 3? %INCLUDE'myconnect.dat';

在上面的示例中,OPTIONS NOSOURCE2阻止包含的代码显示在SAS日志中。 指定SOURCE2会在SAS日志中列出所包含文件的内容。 NOSOURCE2是默认设置。

5)使用SAS 9.1及更高版本,您可以使用Proc PWENCODE程序创建编码密码,可以批量使用SAS程序中的纯文本密码。

http://support.sas.com/onlinedoc/913/getDoc/proc.hlp/a002595988.htm

并选择PWENCODE程序。

Proc语法如下所示。 编码的密码输出到日志。

proc pwencode in =“plaintextPassword”; 跑;

没有安全的方法来定义ODBC连接!

每个人都可以使用Metadata API读取身份验证域,用户名和编码密码。 linux管理员或root用户可以访问任何文件系统,包括主目录和它的password.sas文件。

SAS还提供ChangePassPhrase以将存储的密码降级为较旧的SAS PWENCODE方法。 如果您知道编码密码,则可以通过https://decrypt-password.appspot.com/sas-pwdecode/在线解码。

有时用于不同服务的登录凭据。 FTP或MAIL的用户名和密码也可用于ssh。 文件和元数据不是安全存储。

对不起,不能写评论,但%superq -Trick确实有效。 像这样使用它:

proc sql;
   select * from set_encrypedon (pw="%SUPERQ(_password)");
quit;

你有一个名为_password的宏变量。

不幸的是,这不能包含在宏中

%macro pwd();
  "%SUPERQ(_password)"
%mend;

因为然后MPRINT会再次记录您的密码。

当SYMGET在CONNECT语句中不起作用时,请尝试%SUPERQ引用功能。 它还解析了宏变量,而没有在LOG中显示它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM