Skip to content

Commit

Permalink
add simple auth
Browse files Browse the repository at this point in the history
  • Loading branch information
dayesouza committed Nov 5, 2024
1 parent 7601dc1 commit 759f0af
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 46 deletions.
130 changes: 130 additions & 0 deletions DEPLOYING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Deploying the app

#### Recommended configuration:

- *Minimum disk space*: 8GB

- *Minimum memory*: 4GB
- If too many users using at the same time, it might need to be higher.

## Azure

You can modify the code and deploy the container, or use our default container hosted on ghcr.io.

### Deploying your container
#### TODO

### Using ghcr.io

**Prerequisites**

- Azure Account: Ensure you have an [active Azure subscription](https://azure.microsoft.com/en-us/pricing/purchase-options/azure-account?msockid=1e4bc940d7cf6738158eda91d616667e).

- Terraform: Install Terraform on your local machine. You can download it from [terraform.io](https://developer.hashicorp.com/terraform/install?product_intent=terraform).

- Azure CLI: Install Azure CLI. You can download it from [docs.microsoft.com](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli).

**Steps**

1. Set Up Azure CLI
Login to Azure:

`az login`

This will open a browser window for you to authenticate.
Set the Subscription:
If you have multiple subscriptions, set the one you wish to use:

`az account set --subscription "your-subscription-id"`

Create a Directory for Your Project:

```
mkdir my-terraform-app
cd my-terraform-app
```
2. Use our Terraform Configuration File:
Download the [terraform configuration file here](https://github.com/microsoft/intelligence-toolkit/blob/main/deploy/azure/main.tf)
-Modify the `variables` default field to match your desired resource configuration
- az_webapp_name (change necessary. Should be unique within Global Azure)
- az_rg_name (change optional)
- location (change optional)
- az_asp_name (change optional)
3. Initialize Terraform
`terraform init`
This command downloads the Azure provider and sets up your workspace.
4. Create an Execution Plan
Plan the Deployment:
`terraform plan`
This command creates an execution plan, which lets you preview the changes that Terraform will make to your infrastructure.
5. Apply the Execution Plan
Deploy the Resources:
`terraform apply`
Terraform will prompt you for confirmation before making any changes. Type yes and press Enter.
6. Verify Deployment
Check the Resources in Azure Portal:
Go to the Azure Portal and verify that the resources have been created.
Check the deployed URL:
`<az_webapp_name>.azurewebsites.net`
## AWS
Wait for step 1 to be set as complete before starting step 2. The whole process will take up to 20 minutes.
1. Launch the infrastructure deploy:
- Give it a sugestive name since you'll be using it in the next step.
[![launch-stack](https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=itk-infra-stack&templateURL=https://s3.us-east-1.amazonaws.com/cf-templates-19n482mly1fba-us-east-1/2024-10-07T124926.165Z3xc-infrastructure.yaml)
2. Launch the code deploy
- In VPC Configuration, you should select the resources created by the previous step: <u>VPCId, PublicSubnetAId, PublicSubnetBId, PrivateSubnetAId, PrivateSubnetBId</u>
[![launch-stack](https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=itk-code-stack&templateURL=https://s3.us-east-1.amazonaws.com/cf-templates-19n482mly1fba-us-east-1/2024-10-07T125858.730Zlsu-2-development.yaml)
Once step 2 it's complete, in the output tab, you'll see the deployed URL.
**Note: This code doesn't have auth, so this URL will be open to the internet.**
## Environment configuration
`MODE: CLOUD` to hide Settings page so users can't change configuration that would affect other users experiences.
`AUTH_ENABLED: TRUE` if you would like to limit access into the app by user and password defined in a .secrets.toml file inside .streamlit:
```
[passwords]
user_test = "user123"
...
```
Inserting secrets.toml file to the web app:
Add a value of user=password separating each user by `;` to your web app environment.
`USER_CREDENTIALS="user1=pass1;user2=pass2"`
53 changes: 12 additions & 41 deletions DEVELOPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

## Running the app


## GPT settings

You can configure your OpenAI access when running the app via `Settings page`, or using environment variables.
Expand Down Expand Up @@ -104,8 +103,8 @@ See the documentation and an example of how to run the code with your data to ob

##### Recommended configuration:

- *Minimum disk space*: 10GB
- *Minimum memory*: 8GB
- *Minimum disk space*: 8GB
- *Minimum memory*: 4GB

Download, install and then open docker app: https://www.docker.com/products/docker-desktop/

Expand All @@ -122,56 +121,28 @@ Use `cd `+ the path to the folder. For example:

`cd C:\Users\user01\projects\intelligence-toolkit`

Pull the latest built image:
` docker pull ghcr.io/microsoft/intelligence-toolkit:latest`

or build it with your own code:
Build it with your own code:

`docker build . -t intelligence-toolkit`

Once the pull/build ir fininshed, run the docker container:

- via shell:

`docker run -d -p 80:80 intelligence-toolkit --name intelligence-toolkit`

Open [localhost:80](http://localhost:80)

## Deploying

#### Recommended configuration:

- *Minimum disk space*: 10GB
Or pull the latest built image:

- *Minimum memory*: 8GB
- If too many users using at the same time, it might need to be higher.


### Using AWS

Wait for step 1 to be set as complete before starting step 2. The whole process will take up to 20 minutes.

1. Launch the infrastructure deploy:

- Give it a sugestive name since you'll be using it in the next step.

[![launch-stack](https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=itk-infra-stack&templateURL=https://s3.us-east-1.amazonaws.com/cf-templates-19n482mly1fba-us-east-1/2024-10-07T124926.165Z3xc-infrastructure.yaml)

2. Launch the code deploy
- In VPC Configuration, you should select the resources created by the previous step: <u>VPCId, PublicSubnetAId, PublicSubnetBId, PrivateSubnetAId, PrivateSubnetBId</u>
` docker pull ghcr.io/microsoft/intelligence-toolkit:latest`

[![launch-stack](https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=itk-code-stack&templateURL=https://s3.us-east-1.amazonaws.com/cf-templates-19n482mly1fba-us-east-1/2024-10-07T125858.730Zlsu-2-development.yaml)

Once the pull/build is fininshed, run the docker container:

Once step 2 it's complete, in the output tab, you'll see the deployed URL.
- via shell:

**Note: This code doesn't have auth, so this URL will be open to the internet.**
With `<container-name>` being `intelligence-toolkit` if you used docker build or `ghcr.io/microsoft/intelligence-toolkit:latest` if you used docker pull.

### Using Azure
`docker run -d --name intelligence-toolkit -p 80:80 <container-name>`

In [this tutorial](https://dev.to/keneojiteli/deploy-a-docker-app-to-app-services-on-azure-5d3h), you can learn how to create the necessary services in azure.
Open [localhost:80](http://localhost:80)

From there, you can deploy it manually as described, or use [our YAML file](/.vsts-ci.yml) to automatically deploy to your environment.
## Deploying
See [instructions]('./DEPLOYING.md')


# Lifecycle Scripts
Expand Down
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor
ENV PATH="/root/.local/bin:$PATH"

COPY . .
RUN rm -rf .streamlit/app_secrets.toml
RUN poetry install --only main

# Run application
Expand Down
8 changes: 4 additions & 4 deletions app/Home.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ def main():
page_icon=f"{path}myapp.ico",
page_title="Intelligence Toolkit | Home",
)

load_multipage_app()
transparency_faq, mermaid_text = get_readme_and_mermaid()

st.markdown(
transparency_faq
)
st.markdown(transparency_faq)

mermaid.mermaid(
code=mermaid_text,
height=1000,
)



if __name__ == "__main__":
main()
main()
70 changes: 70 additions & 0 deletions app/components/app_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright (c) 2024 Microsoft Corporation. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project.
#

import hmac
import os

import streamlit as st
import toml

credentials_string = os.getenv("USER_CREDENTIALS")
credentials_dict = {}


def check_password() -> bool:
"""Returns `True` if the user had a correct password."""

def login_form():
"""Form with widgets to collect user information"""
with st.form("Credentials"):
st.text_input("Username", key="username")
st.text_input("Password", type="password", key="password")
st.form_submit_button("Log in", on_click=password_entered)

def password_entered():
"""Checks whether a password entered by the user is correct."""
if st.session_state["username"] in st.secrets[
"passwords"
] and hmac.compare_digest(
st.session_state["password"],
st.secrets.passwords[st.session_state["username"]],
):
st.session_state["password_correct"] = True
del st.session_state["password"] # Don't store the password.
else:
st.session_state["password_correct"] = False

# Return True if the username + password is validated.
if st.session_state.get("password_correct", False):
return True

# Show inputs for username + password.
login_form()
if "password_correct" in st.session_state:
st.error("User not known or password incorrect")
st.stop()
return False


def load_passwords() -> None:
if credentials_string:
user_pairs = credentials_string.split(";")
for pair in user_pairs:
if ":" in pair:
user, password = pair.split(":")
credentials_dict[user] = password

secrets_content = {"passwords": credentials_dict}

secrets_file_path = os.path.join(".streamlit", "secrets.toml")
if not os.path.exists(secrets_file_path):
with open(secrets_file_path, "w") as secrets_file:
toml.dump(secrets_content, secrets_file)
else:
with open(secrets_file_path) as secrets_file:
current_secrets = toml.load(secrets_file)
if current_secrets != secrets_content:
with open(secrets_file_path, "w") as secrets_file:
toml.dump(secrets_content, secrets_file)
print("User auth info updated")
19 changes: 19 additions & 0 deletions app/components/app_loader.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
# Copyright (c) 2024 Microsoft Corporation. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project.
#
import os

import streamlit as st
from streamlit.source_util import (
_on_pages_changed,
get_pages,
)

import app.components.app_mode as am
import app.components.app_user as au
from app.components.app_auth import check_password, load_passwords
from app.javascript.styles import add_styles


def load_multipage_app(sv=None):
if os.getenv("AUTH_ENABLED") == "TRUE":
load_passwords()
check_password()
if os.getenv("MODE") == "CLOUD":
current_pages = get_pages("Home.py")

for key, value in current_pages.items():
if value["page_name"] == "Settings":
del current_pages[key]
break
_on_pages_changed.send()

# Load user if logged in
user = au.AppUser()
user.view_get_info()
Expand Down
4 changes: 4 additions & 0 deletions app/components/app_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Licensed under the MIT license. See LICENSE file in the project.
#
import streamlit as st

from app.javascript.scripts import get_auth_user
from app.util.enums import Mode
from app.util.session_variables import SessionVariables
Expand All @@ -24,6 +25,9 @@ def _set_user(self, username):
self.sv.username.value = username

def view_get_info(self):
if st.session_state.get("username"):
self._set_user(st.session_state["username"])

if self.sv.username.value:
st.sidebar.write(f"Logged in as {self.sv.username.value}")

Expand Down
Loading

0 comments on commit 759f0af

Please sign in to comment.