2011-11-16 127 views
4

我們希望從我們的SAS代碼中的ODBC連接字符串中刪除硬編碼的密碼,並且還可以防止任何密碼出現在SAS日誌文件中。SAS中的ODBC密碼安全

似乎有很多的白皮書討論如何去做這件事,但我要麼找到他們的問題,要麼不能讓他們工作。

每次爲PW提示用戶不是一個可行的選擇。 此外,將密碼存儲在宏變量中是一種可接受的方法,只要您有辦法在打開MACROGEN和SYMBOLGEN選項的情況下將其禁止打印到日誌中。

未遂1 - 編碼link to whitepaper here

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

給出:

{sasenc}ACFD24061BF77D7D5362EE7C2D00D08B 

如果我在我的代碼編碼值替換我的明文密碼,那麼ODBC直通語句運行正常。

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; 

而且日誌正確地掩蓋了XXXXXXX的值。

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密碼恰好在其他地方使用,這是關於它。

未遂2 - 使用SYMGETlink to whitepaper here

這樣做的問題是,我根本無法描述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開啓的技術。

回答

4

Rob,我們遇到了類似的問題,並提出了一種不同的方法,允許我們所有的團隊成員運行相同的程序,而無需在程序中存儲我們的ID /密碼。它要求每個團隊成員安全地存儲文本文件(沒有權限,除了所有者)SAS可以訪問。

這裏的ID /密碼文件的內容的一個示例:

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

我們在UNIX服務器上運行,所以我們存儲我們indivual ID /密碼文件鎖在我們的主目錄,以便沒有人可以訪問它,在這種情況下它被命名爲「.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; 
+0

嗨,感謝您的快速回復。是的,我希望實現一些不需要我們用ODBC代碼來包裝每條SQL語句的東西。我們有一個很大的代碼庫,我並不想更新....我沒有在我的原始需求中指定,但我開始認爲這可能是唯一的方法,所以我要去繼續並將您的回答標記爲答案。再次感謝... –

+0

此外,您可能希望將MACROGEN添加到您的系統選項列表中以禁用,因爲它也會打印它。需要禁用的完整列表如下: 'option nomprint nomacrogen nosymbolgen; *必須禁用; 選項mlogic源碼source2筆記; *可能爲左;' –

3

因此,我還聯繫了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直通,您可以通過在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直通,則可以將您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」;跑;

+0

我也有同樣的問題,symget函數在connect語句中沒有得到解決。我很沮喪。因此,如果我理解正確,SAS會在官方白皮書中推薦解決方案,然後否認解決方案有效?如果你問我,所有推薦的解決方案都是垃圾。 – ercan

+1

@ ercan Yup,不能同意更多。 RWill的解決方案是現在正確鎖定內容的唯一方法,並且需要大量工作。至少他們可以提供一些可用作標準的實用程序,以及如何實施和使用它們的說明。我們最終按照RWill的建議做了一些工作,並且在工作的同時,每個公司都不需要重新發明輪子。它還需要修改每個使ODBC調用的代碼片段=/ –

1

當SYMGET在CONNECT語句中不起作用時,請嘗試使用%SUPERQ引用函數。它也解析了宏變量而不在LOG中顯示它。

+1

對不起 - 我希望這是真的,但事實並非如此。見代碼:'%let x = testds; %macro z; data%superq(x); blah = 1; 跑; %修復; %z;' –

+0

羅伯特是對的。只要在宏中使用「連接到odbc(...)」,並且打開了* mprint *選項,日誌就會以明文形式包含密碼。 – ercan

1

對不起,不能發表評論,但%superq -Trick真的有用。像這樣使用它:

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

其中有一個名爲_password的宏變量。

不幸的是,這不能被包裹成一個宏像

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

因爲那時MPRINT將再次登錄密碼。

+0

感謝馬丁 - 現在沒有時間了,但我會盡快檢查一下。 –

+1

啊 - 好的,我明白你在哪裏帶着這個。所以不幸的是,我不能保證所有在我公司編寫代碼的人都會在宏之外有'proc sql'語句,因此我不能使用這種技術。只要有人把這個陳述放在一個宏中(這幾乎是不可避免的),它就會變得不安全。謝謝你的建議。 –

2

沒有安全的方法來定義ODBC連接!

通過使用元數據API,每個人都可以讀取授權域,用戶名和編碼密碼。 linux管理員或root用戶可以訪問任何文件系統,包括主目錄和password.sas文件。

SAS還提供ChangePassPhrase以將存儲的密碼降級到舊的SAS PWENCODE方法。如果您知道編碼的密碼,則可以對其進行解碼,例如,在線地址爲https://decrypt-password.appspot.com/sas-pwdecode/

有時用於不同服務的登錄憑證。 FTP或MAIL的用戶名和密碼也可以用於ssh。文件和元數據不是安全的商店。

+0

你是什麼意思「每個人都可以讀取授權域名」?只有那些有權訪問存儲帳戶的元數據標識的用戶(直接以用戶的元數據標識或針對他們所屬的組)才能訪問保存在auth域中的帳戶。 – LokMac