Combine Amazon Redshift row-level safety with Amazon Redshift native IdP authentication

0
1

1269

1269
1269

1269 Amazon Redshift 1269 is a totally managed, 1269 petabyte-scale knowledge warehouse service within 1269 the cloud. You can begin 1269 with just some hundred gigabytes 1269 of information and scale to 1269 a petabyte or extra. This 1269 allows you to use your 1269 knowledge to amass new insights 1269 for what you are promoting 1269 and clients.

1269
1269

1269 As enterprise clients look to 1269 construct their knowledge warehouse on 1269 Amazon Redshift, they’ve enterprise necessities 1269 to implement enough fine-grained entry 1269 controls to manipulate who can 1269 entry which rows of their 1269 delicate knowledge primarily based on 1269 the consumer profiler. Moreover, many 1269 organizations wish to entry Amazon 1269 Redshift utilizing their present identification 1269 supplier (IdP) whereas sustaining these 1269 compliance and safety necessities round 1269 their knowledge. With out correct 1269 built-in options to implement row-level 1269 and safe authentication, you will 1269 have to develop further options 1269 resembling views, or attempt to 1269 combine third-party options round your 1269 knowledge to implement safety.

1269
1269

1269 With the introduction of 1269 row-level safety in Amazon Redshift 1269 , you may prohibit consumer 1269 entry on the row stage. 1269 Moreover, we’ve launched a 1269 native IdP performance 1269 that can assist you 1269 implement authentication and authorization together 1269 with your alternative of enterprise 1269 intelligence (BI) instruments in a 1269 seamless method.

1269
1269

1269 Amazon Redshift row-level safety (RLS) 1269 offers granular entry management over 1269 your delicate knowledge. It does 1269 this by utilizing RLS insurance 1269 policies to find out which 1269 rows to return within the 1269 question outcome units.

1269
1269

1269 On this submit, we stroll 1269 you thru an instance on 1269 how one can implement row-level 1269 safety in Amazon Redshift whereas 1269 utilizing present IdP credentials to 1269 simplify authentication and managing permissions. 1269 You should utilize this versatile 1269 answer to offer full management 1269 over knowledge entry whereas sustaining 1269 authorization utilizing your present IdP.

1269
1269

1269 Resolution overview

1269
1269

1269 For our use case, a 1269 corporation requires row-level safety to 1269 limit entry to gross sales 1269 efficiency knowledge to particular states 1269 and their allotted salesperson. Now 1269 we have the next enterprise 1269 guidelines and circumstances:

1269
1269

    1269
    1269

  • 1269 Alice, the salesperson for NY, 1269 ought to have entry to 1269 NY gross sales knowledge solely
  • 1269
    1269

  • 1269 Bob, the salesperson for CA, 1269 ought to get entry to 1269 CA gross sales knowledge solely
  • 1269
    1269

  • 1269 Charlie, the gross sales supervisor 1269 for the North America area, 1269 ought to have entry to 1269 gross sales knowledge for all 1269 states
  • 1269
    1269

  • 1269 Jen, who belongs to HR 1269 division, shouldn’t have entry to 1269 any gross sales knowledge
  • 1269
    1269

1269
1269

1269 The next diagram illustrates the 1269 answer structure we implement to 1269 resolve this downside assertion utilizing 1269 Amazon Redshift row-level safety and 1269 Amazon Redshift native IdP authentication.

1269
1269

Solution Overview

1269
1269

1269 The answer incorporates the next 1269 steps:

1269
1269

    1269
    1269

  1. 1269 Create RLS insurance policies to 1269 offer fine-grained entry management for 1269 row-level knowledge on the Gross 1269 sales desk.
  2. 1269
    1269

  3. 1269 Create Amazon Redshift roles for 1269 every of the completely different 1269 Azure AD teams and assign 1269 related permissions to the desk.
  4. 1269
    1269

1269
1269

1269 With native IdP, roles get 1269 created routinely primarily based on 1269 Azure teams. Nonetheless, as a 1269 finest observe, we’re pre-creating the 1269 Amazon Redshift roles and assigning 1269 related permissions.

1269
1269

    1269
    1269

  1. 1269 Connect row-level safety insurance policies 1269 to the roles.
  2. 1269
    1269

  3. 1269 Configure a JDBC or ODBC 1269 driver in your SQL shopper 1269 to make use of Azure 1269 AD federation and use Azure 1269 AD login credentials to sign 1269 up.
  4. 1269
    1269

  5. 1269 Upon profitable authentication, Azure AD 1269 points an authentication token (OAuth 1269 token) again to the Amazon 1269 Redshift driver.
  6. 1269
    1269

  7. 1269 The driving force forwards the 1269 authentication token to the Amazon 1269 Redshift cluster to provoke a 1269 brand new database session. Amazon 1269 Redshift verifies and validates the 1269 authentication token.
  8. 1269
    1269

  9. 1269 Amazon Redshift calls the Azure 1269 Graph API to acquire the 1269 consumer’s group membership.
  10. 1269
    1269

  11. 1269 Amazon Redshift maps the logged-in 1269 Azure AD consumer to the 1269 Amazon Redshift consumer and maps 1269 the Azure AD teams to 1269 Amazon Redshift roles.
  12. 1269
    1269

  13. 1269 The Amazon Redshift roles are 1269 pre-mapped with the RLS insurance 1269 policies talked about in step 1269 3. This enables the respective 1269 customers to question the fine-grained 1269 row-level entry knowledge from the 1269 shopper.
  14. 1269
    1269

1269
1269

1269 Stipulations

1269
1269

1269 To implement this answer, it’s 1269 essential to have the next 1269 stipulations:

1269
1269
1269 1269

1269 Implement your Amazon Redshift native 1269 IdP

1269
1269

1269 To arrange your Amazon Redshift 1269 native IdP setup, seek advice 1269 from 1269 Combine Amazon Redshift native IdP 1269 federation with Microsoft Azure AD 1269 utilizing a SQL shopper 1269 . Comply with the steps 1269 to arrange your Azure software 1269 and acquire Azure AD info 1269 for the Amazon Redshift IdP.

1269
1269

1269 For this submit, we’ve created 1269 the next 4 teams in 1269 Azure AD:

1269
1269

    1269
    1269

  • 1269 sales_ny
  • 1269
    1269

  • 1269 sales_ca
  • 1269
    1269

  • 1269 sales_manager
  • 1269
    1269

  • 1269 hr_group
  • 1269
    1269

1269
1269

1269 Then we created the next 1269 4 customers in Azure AD:

1269
1269

    1269
    1269

  • 1269 Alice 1269 – The salesperson in 1269 NY state
  • 1269
    1269

  • 1269 Bob 1269 – The salesperson in 1269 CA state
  • 1269
    1269

  • 1269 Charlie 1269 – The supervisor for 1269 the North America area
  • 1269
    1269

  • 1269 Jen 1269 – A member of 1269 the HR group
  • 1269
    1269

1269
1269

1269 Add the respective customers to 1269 their applicable group:

1269
1269

    1269
    1269

  • 1269 Alice 1269 1269 sales_ny
  • 1269
    1269

  • 1269 Bob 1269 1269 sales_ca
  • 1269
    1269

  • 1269 Charlie 1269 1269 sales_manager
  • 1269
    1269

  • 1269 Jen 1269 1269 HR
  • 1269
    1269

1269
1269

1269 Subsequent, we have to register 1269 the IdP in Amazon Redshift 1269 utilizing the next command:

1269
1269

1269
1269

 1269 CREATE IDENTITY PROVIDER rls_idp TYPE
azure  1269 NAMESPACE 'aad'
PARAMETERS '{
"issuer":"https://sts.home windows.web/87f4aa26-78b7-410e-bf29-57b39929ef9a/",
"viewers":["https://analysis.windows.net/powerbi/connector/AmazonRedshift",
"api://991abc78-78ab-4ad8-a123-zf123ab03612p"],
"client_id":"123ab555-a321-666d-7890-11a123a44890",
"client_secret":"KiG7Q~FEDnE.VsWS1IIl7LV1R2BtA4qVv2ixB" }'
;

1269
1269

1269
1269

1269 Within the previous assertion, the 1269 kind azure signifies that the 1269 supplier particularly facilitates communication with 1269 Microsoft Azure AD. We use 1269 the next parameters to gather 1269 Azure AD info (for extra 1269 info, seek advice from 1269 Accumulate Azure AD Info 1269 in 1269 Combine Amazon Redshift native IdP 1269 federation with Microsoft Azure AD 1269 utilizing a SQL shopper 1269 ).

1269
1269

    1269
    1269

  • 1269 issuer 1269 – The issuer ID 1269 to belief when a token 1269 is obtained. The distinctive identifier 1269 for the 1269 tenant_id 1269 is appended to the 1269 issuer.
  • 1269
    1269

  • 1269 client_id 1269 – The distinctive public 1269 identifier of the appliance registered 1269 with the IdP. This may 1269 be known as the appliance 1269 ID.
  • 1269
    1269

  • 1269 client_secret 1269 – A secret identifier, 1269 or password, identified solely to 1269 the IdP and the registered 1269 software.
  • 1269
    1269

  • 1269 viewers 1269 – The appliance ID 1269 that’s assigned to the appliance 1269 in Azure. For this submit, 1269 we join with Amazon Redshift 1269 utilizing Energy BI Desktop and 1269 SQL Workbench/J. The viewers worth 1269 is hardcoded for Energy BI 1269 desktop, for instance 1269 https://evaluation.home windows.web/powerbi/connector/AmazonRedshift 1269 . The second viewers 1269 worth is for the SQL 1269 shopper, which you get from 1269 the appliance ID URI within 1269 the OAuth software. For instance, 1269 1269 api://991abc78-78ab-4ad8-a123-zf123ab03612p 1269 .
  • 1269
    1269

1269
1269

1269 Use the next command to 1269 view the registered IdP on 1269 Amazon Redshift:

1269
1269

1269
1269

 1269 DESC IDENTITY PROVIDER rls_idp;

1269
1269

1269
1269

Native IdP - data

1269
1269

1269 Use the next command to 1269 view all of the IdPs 1269 registered:

1269
1269

1269
1269

 1269 choose * from svv_identity_providers;

1269
1269

1269
1269

1269 The next Gross sales desk 1269 incorporates details about every salesperson, 1269 the respective state they cowl, 1269 and their whole gross sales 1269 quantity:

1269
1269

1269
1269

 1269 CREATE TABLE SALES (sales_person VARCHAR(30),  1269 state CHAR(2), "total_sales" INT);
INSERT INTO  1269 SALES VALUES ('Alice', 'NY', 5000);
INSERT  1269 INTO SALES VALUES ('Bob', 'CA',  1269 6000);
INSERT INTO SALES VALUES ('Sally',  1269 'IL', 7000);

1269
1269

1269
1269

Sales data

1269
1269

1269 Now we create 4 roles 1269 within the Amazon Redshift cluster 1269 primarily based on the teams 1269 that we created on the 1269 Azure AD portal and assign 1269 related permissions to them. This 1269 simplifies administration by assigning completely 1269 different permissions to completely different 1269 roles and assigning them to 1269 completely different customers.

1269
1269

1269 The position identify within the 1269 Amazon Redshift cluster seems to 1269 be like 1269 <namespace>:<azure_ad_group_name> 1269 , the place the namespace 1269 is the one we supplied 1269 within the IdP creation command 1269 ( 1269 aad 1269 ) and the group identify 1269 is the Azure AD group. 1269 See the next code:

1269
1269

1269
1269

 1269 CREATE ROLE "aad:sales_ny";
CREATE ROLE "aad:sales_ca";
CREATE  1269 ROLE "aad:sales_manager";
CREATE ROLE "aad:hr";

1269
1269

1269
1269

1269 Now we grant permission to 1269 the Amazon Redshift position on 1269 the suitable tables. For this 1269 submit, we assign SELECT permission 1269 on the Gross sales desk 1269 for all 4 roles:

1269
1269

1269
1269

 1269 GRANT SELECT ON TABLE SALES  1269 TO ROLE "aad:sales_ny";
GRANT SELECT ON  1269 TABLE SALES TO ROLE "aad:sales_ca";
GRANT  1269 SELECT ON TABLE SALES TO  1269 ROLE "aad:sales_manager";
GRANT SELECT ON TABLE  1269 SALES TO ROLE "aad:hr";

1269
1269

1269
1269

1269 Use the next command to 1269 view all of the roles 1269 within the cluster:

1269
1269
1269 1269

roles information

1269
1269

1269 Create a row-level safety coverage

1269
1269

1269 Let’s implement an RLS coverage 1269 on the Gross sales desk 1269 to limit entry to gross 1269 sales efficiency info for a 1269 salesman particular to a specific 1269 state. We create the next 1269 coverage:

1269
1269

1269
1269

 1269 CREATE RLS POLICY policy_sales_ny
WITH (state  1269 char(2))
USING (state="NY");
CREATE RLS POLICY policy_sales_ca
WITH  1269 (state char(2))
USING (state="CA");

1269
1269

1269
1269

1269 The gross sales supervisor can 1269 also be required to view 1269 gross sales throughout the North 1269 American area. For this, we 1269 create the next coverage:

1269
1269

1269
1269

 1269 CREATE RLS POLICY policy_sales_all
USING (true);

1269
1269

1269
1269

1269 The 1269 policy_sales_all 1269 coverage permits the gross 1269 sales supervisor to view all 1269 the knowledge within the gross 1269 sales desk.

1269
1269

1269 Connect the row-level safety coverage 1269 to roles

1269
1269

1269 Now we’ve to connect the 1269 row-level safety insurance policies to 1269 their respective Amazon Redshift roles 1269 in order that when the 1269 consumer logs in utilizing their 1269 Amazon Redshift native IdP, they 1269 will get fine-grained entry to 1269 the data.

1269
1269

1269
1269

 1269 ATTACH RLS POLICY policy_sales_ny ON  1269 public.gross sales TO ROLE "aad:sales_ny";
ATTACH  1269 RLS POLICY policy_sales_ca ON public.gross  1269 sales TO ROLE "aad:sales_ca";
ATTACH RLS  1269 POLICY policy_sales_all ON public.gross sales  1269 TO ROLE "aad:sales_manager";

1269
1269

1269
1269

1269 For the HR position, we 1269 haven’t created or connected any 1269 RLS coverage as a result 1269 of we don’t need any 1269 consumer from the HR group 1269 to get entry to gross 1269 sales data.

1269
1269

1269 Allow row-level safety on the 1269 desk

1269
1269

1269 Now let’s allow row-level safety 1269 on the respective tables. On 1269 this demo, we allow the 1269 RLS coverage on the Gross 1269 sales desk utilizing the next 1269 command:

1269
1269

1269
1269

 1269 ALTER TABLE public.gross sales ROW  1269 LEVEL SECURITY ON;

1269
1269

1269
1269

1269 Use the next command to 1269 view the RLS insurance policies:

1269
1269

1269
1269

 1269 SELECT * FROM svv_rls_attached_policy;

1269
1269

1269
1269

RLS policy - Data

1269
1269

1269 Check row-level safety utilizing Energy 1269 BI Desktop

1269
1269

1269 On this instance, we use 1269 Microsoft Energy BI Desktop to 1269 attach with Amazon Redshift utilizing 1269 a local IdP. For this 1269 answer, use 1269 Microsoft Energy BI Desktop- Model: 1269 2.102.683.0 64-bit 1269 and above.

1269
1269

    1269
    1269

  1. 1269 In your Microsoft Energy BI 1269 Desktop, select 1269 Get knowledge 1269 .
  2. 1269
    1269

1269
1269

Native IdP- PowerBI Desktop-Login

1269
1269

    1269
    1269

  1. 1269 Seek for the Amazon Redshift 1269 connector, select it, and select 1269 1269 Join 1269 .
  2. 1269
    1269

1269
1269

Native IdP- PowerBI Desktop-Login

1269
1269

    1269
    1269

  1. 1269 For 1269 Server 1269 , enter your Amazon Redshift 1269 cluster’s endpoint. For instance: 1269 test-cluster.ct4abcufthff.us-east-1.redshift.amazonaws.com 1269 .
  2. 1269
    1269

  3. 1269 For 1269 Database 1269 , enter your database identify 1269 (for this submit, we enter 1269 1269 dev 1269 ).
  4. 1269
    1269

  5. 1269 Select 1269 OK 1269 .
  6. 1269
    1269

1269
1269

Native IdP- PowerBI Desktop-connection

1269
1269

    1269
    1269

  1. 1269 Select 1269 Microsoft Account 1269 .
  2. 1269
    1269

1269
1269

Native IdP- PowerBI Desktop-Login

1269
1269

    1269
    1269

  1. 1269 Select 1269 Sign up 1269 .
  2. 1269
    1269

1269
1269

RLS-Native IdP- PowerBI Desktop-Login

1269
1269

    1269
    1269

  1. 1269 Enter your Microsoft Account credentials 1269 within the authorization dialog. For 1269 this instance, we sign up 1269 with consumer Alice.
  2. 1269
    1269

1269
1269

    1269
    1269

  1. 1269 Select 1269 Subsequent 1269 .
  2. 1269
    1269

1269
1269

RLS-Native IdP- PowerBI Desktop-Login

1269
1269

1269 As soon as linked, you 1269 will note the message “You 1269 might be presently signed in.”

1269
1269

    1269
    1269

  1. 1269 Select 1269 Join 1269 .
  2. 1269
    1269

1269
1269

1269
1269

1269 As proven within the following 1269 screenshot, Azure AD consumer Alice 1269 is ready to authenticate utilizing 1269 an Amazon Redshift native IdP, 1269 and the RLS insurance policies 1269 had been utilized routinely, permitting 1269 Alice to entry gross sales 1269 efficiency info for under NY 1269 state.

1269
1269

RLS-Native IdP- PowerBI Desktop-Authorized to view respective data

1269
1269

1269 Equally, we are able to 1269 strive signing in as consumer 1269 Bob and see solely CA 1269 state info.

1269
1269

RLS-Native IdP- PowerBI Desktop-UnAuthorized to view respective data

1269
1269

1269 Charlie belongs to the supervisor 1269 position the place the view 1269 all coverage has been utilized, 1269 so when he indicators in, 1269 he is ready to view 1269 all of the rows within 1269 the gross sales desk.

1269
1269

RLS-Native IdP- PowerBI Desktop-Authorized to view data

1269
1269

1269 Lastly, when Jen indicators in, 1269 she will entry the desk, 1269 however isn’t in a position 1269 to view any gross sales 1269 data as a result of 1269 no RLS coverage has been 1269 connected to the HR position.

1269
1269

RLS-Native IdP- PowerBI Desktop-UnAuthorized to view data

1269
1269

1269 If we haven’t granted SELECT 1269 on the gross sales desk 1269 to the position 1269 aad:hr 1269 , which Jen belongs to, 1269 then she will’t entry the 1269 gross sales desk.

1269
1269

RLS-Native IdP- PowerBI Desktop-UnAuthorized to access table

1269
1269

1269 Check row-level safety utilizing SQL 1269 Workbench/J

1269
1269

1269 Now we check row-level safety 1269 with an Amazon Redshift native 1269 IdP utilizing SQL Workbench/J.

1269
1269

    1269
    1269

  1. 1269 Create a brand new connection 1269 in SQL Workbench/J and select 1269 Amazon Redshift as the driving 1269 force.
  2. 1269
    1269

  3. 1269 Select 1269 Handle drivers 1269 and add all of 1269 the recordsdata from the downloaded 1269 AWS JDBC driver pack .zip 1269 file. (Bear in mind to 1269 unzip the file.)
  4. 1269
    1269

1269
1269

1269 Be sure that to make 1269 use of the Amazon Redshift 1269 driver 2.1.0.4 onwards, as a 1269 result of all earlier Amazon 1269 Redshift driver variations don’t assist 1269 the Amazon Redshift native IDP 1269 characteristic.

1269
1269

Native IdP- Workbench/J drivers

1269
1269

    1269
    1269

  1. 1269 For URL, enter 1269 jdbc:redshift 1269 :// 1269 <cluster endpoint>:<port>:<databasename> 1269 . For instance: 1269 jdbc:redshift 1269 :// 1269 test-cluster.ab6yejheyhgf.us-east-1.redshift.amazonaws.com:5439/dev 1269 .
  2. 1269
    1269

1269
1269

Native IdP- Workbench/J Connection

1269
1269

    1269
    1269

  1. 1269 On the 1269 Driver properties 1269 tab, add the next 1269 properties:
    1269 1269

      1269
      1269 1269

    1. 1269 plugin_name 1269 1269 com.amazon.redshift.plugin.BrowserAzureOAuth2CredentialsProvider
    2. 1269
      1269 1269

    3. 1269 listen_port 1269 – 7890
    4. 1269
      1269 1269

    5. 1269 idp_response_timeout 1269 – 50
    6. 1269
      1269 1269

    7. 1269 scope 1269 – Enter the scope 1269 worth from the OAuth software. 1269 For instance, 1269 api://991abc78-78ab-4ad8-a123-zf123ab03612p/jdbc_login 1269 .
    8. 1269
      1269 1269

    9. 1269 client_id 1269 – Enter the client_id 1269 worth from the OAuth software. 1269 For instance, 1269 991abc78-78ab-4ad8-a123-zf123ab03612p 1269 .
    10. 1269
      1269 1269

    11. 1269 idp_tenant 1269 – Enter the tenant 1269 ID worth from the OAuth 1269 software. For instance, 1269 87f4aa26-78b7-410e-bf29-57b39929ef9a 1269 .
    12. 1269
      1269 1269

    1269

  2. 1269
    1269

1269
1269

Native IdP- Workbench/J Parameters

1269
1269

    1269
    1269

  1. 1269 Select 1269 OK 1269 from SQL Workbench/J.
  2. 1269
    1269

1269
1269

1269 You’re redirected to the browser 1269 to sign up together with 1269 your Azure AD credentials.

1269
1269

1269 As proven within the following 1269 screenshot, Azure AD consumer Alice 1269 is ready to authenticate utilizing 1269 an Amazon Redshift native IdP 1269 and think about solely gross 1269 sales efficiency info for NY 1269 state.

1269
1269

1269
1269

1269 Equally, we are able to 1269 re-authenticate and sign up as 1269 consumer Bob, who is ready 1269 to view gross sales info 1269 particular to CA state.

1269
1269

1269
1269

1269 When Charlie indicators in, he 1269 is ready to view all 1269 of the rows from each 1269 state.

1269
1269

1269
1269

1269 Lastly, when Jen indicators in, 1269 she is ready to entry 1269 the desk, however can’t view 1269 any gross sales data as 1269 a result of no RLS 1269 coverage has been connected to 1269 the HR position.

1269
1269

1269
1269

1269 If we haven’t granted SELECT 1269 on the gross sales desk 1269 to the position aad:hr, which 1269 Jen belongs to, then Jen 1269 can’t entry the gross sales 1269 desk.

1269
1269

1269
1269

1269 Abstract

1269
1269

1269 On this submit, we coated 1269 how one can obtain a 1269 safe end-to-end expertise utilizing Amazon 1269 Redshift native IdP authentication, which 1269 simplifies administration and row-level safety 1269 to allow fine-grained row-level entry 1269 in Amazon Redshift.

1269
1269

1269 For extra details about Amazon 1269 Redshift row-level safety and native 1269 IdP federation, seek advice from:

1269
1269
1269 1269


1269
1269

1269 Concerning the authors

1269
1269

1269 Maneesh Sharma 1269 is a Senior Database 1269 Engineer at AWS with greater 1269 than a decade of expertise 1269 designing and implementing large-scale knowledge 1269 warehouse and analytics options. He 1269 collaborates with varied Amazon Redshift 1269 Companions and clients to drive 1269 higher integration.

1269
1269

1269 Harshida Patel 1269 is a Specialist Sr. 1269 Options Architect, Analytics, with AWS.

1269
1269

1269 Kiran Chinta 1269 is a Software program 1269 Growth Supervisor at Amazon Redshift. 1269 He leads a powerful workforce 1269 in question processing, SQL language, 1269 knowledge safety, and efficiency. Kiran 1269 is obsessed with delivering merchandise 1269 that seamlessly combine with clients’ 1269 enterprise purposes with the suitable 1269 ease of use and efficiency. 1269 In his spare time, he 1269 enjoys studying and taking part 1269 in tennis.

1269
1269

Debu-Panda 1269 Debu Panda 1269 is a Senior Supervisor, 1269 Product Administration, with AWS. He’s 1269 an business chief in analytics, 1269 software platforms, and database applied 1269 sciences, and has greater than 1269 25 years of expertise within 1269 the IT world. Debu has 1269 revealed quite a few articles 1269 on analytics, enterprise Java, and 1269 databases, and has offered at 1269 a number of conferences resembling 1269 AWS re:Invent, Oracle Open World, 1269 and Java One. He’s lead 1269 writer of the EJB 3 1269 in Motion (Manning Publications 2007, 1269 2014) and Middleware Administration (Packt). 1269

1269
1269 1269
1269

1269

LEAVE A REPLY

Please enter your comment!
Please enter your name here