Store data tamperproof using the Python  SDK for immudb — the blazing fast, OSS immutable db
Tags: python, opensource, immutability, database
Published: 2020-09-22 18:08:17

# The Python  SDK for immudb

## Prerequisites

**immu-py** assumes there is an existing instance of the immudb server up and running. 

You can skip the Setup immudb part, if you have immudb already running.

## Setup immudb

**immudb** is **lightweight, high-speed immutable database** for systems and applications. immudb is open source under the [Apache v2.0 License](https://github.com/codenotary/immudb/blob/master/LICENSE).

With [immudb](https://github.com/codenotary/immudb) you can track changes in sensitive data in your transactional databases and then record those changes indelibly in a tamperproof database. immudb makes sure that not just the latest data, but the complete history of, say, your debit/credit transactions is stored unchangeable.

## Setup immudb

If you haven't setup immudb yet, this is the time to do so. You only need to start immudb either as a process, a service or a docker container.

It's up to you if you want to build the Docker /images/blog yourself based on the Dockerfiles in the GitHub repository or use the prebuild ones on Dockerhub.

immudb is using the following defaults:

- Auth user: immudb
- Auth password: immudb
- Service Port: 3322 (immudb)
- Metrics Port: 9497 (Prometheus exporter)

### immudb **Dockerhub**

```shell
docker run -it -d -p 3322:3322 -p 9497:9497 — name immudb codenotary/immudb:latest
```

### standalone Binaries

Each release provides all binaries for different operating systems. you can find these here: [immudb releases](https://github.com/codenotary/immudb/releases)

If you want to build the **binaries**yourself, simply [clone this repo](https://github.com/codenotary/immudb) and run one of the following commands based on your operating system.

```shell
# Linux
GOOS=linux GOARCH=amd64 make immudb-static
# macOS
GOOS=darwin GOARCH=amd64 make immudb-static
# Microsoft Windows
GOOS=windows GOARCH=amd64 make immudb-static
```

Then you can run immudb

```shell
# run immudb in the foreground 
./immudb
# run immudb in the background 
./immudb -d
```

### install immudb as a service

```shell
# install immudb service 
./immudb service install
# check current immudb service status 
./immudb service status
# stop immudb service 
./immudb service stop
# start immudb service 
./immudb service start
```

## Introduction Python SDK for immudb

**immu-py** implements a [grpc] immudb client. A minimalist API is exposed for applications while cryptographic
verifications and state update protocol implementation are fully implemented by this client.
Latest validated immudb state may be kept in the local filesystem when using default `rootService`,
please read [immudb research paper] for details of how immutability is ensured by [immudb].

[grpc]: https://grpc.io/
[immudb research paper]: https://immudb.io/
[immudb]: https://immudb.io/


## Installation

Install the package using pip:

```shell
    pip install git+https://github.com/codenotary/immu-py.git
```

 Then import the client as follows:

```python
    from immudb.client import ImmudbClient
```

Note: immu-py is currently hosted in [Github Packages].

## Supported Versions

immu-py supports the [latest immudb release].

[latest immudb release]: https://github.com/codenotary/immudb/releases/tag/v0.7.1

## Quickstart

[Hello Immutable World!] example can be found in `immudb-client-examples` repo.

[Hello Immutable World!]: https://github.com/codenotary/immudb-client-examples/tree/master/python

## Step by step guide

### Creating a Client

The following code snippets shows how to create a client.

Using default configuration:

```python
    client = ImmudbClient()
```

Setting `immudb` url and port:

```python

    client = ImmudbClient("mycustomurl:someport")
    client = ImmudbClient("10.105.20.32:8899")
```

### User sessions

Use `login` and `logout` methods to initiate and terminate user sessions:

```python
    client.login("usr1", "pwd1");

    // Interact with immudb using logged user

    client.logout();
```
### Encoding

Please note that, in order to provide maximum flexibility, all functions accept byte arrays as parameters. Therefore, unicode strings must be properly encoded.
It is possible to store structured objects, but they must be serialized (e.g., with pickle or json).

### Creating a database

Creating a new database is quite simple:

```python
    client.createDatabase(b"db1");
```

### Setting the active database

Specify the active database with:

```python
    client.useDatabase(b"db1");
```
If not specified, the default databased used is "defaultdb".

### Traditional read and write

immudb provides read and write operations that behave as a traditional
key-value store i.e. no cryptographic verification is done. This operations
may be used when validations can be post-poned:

```python
    client.set(b"k123", b"value123");
    result = client.get(b"k123");
```

### Verified or Safe read and write

immudb provides built-in cryptographic verification for any entry. The client
implements the mathematical validations while the application uses as a traditional
read or write operation:

```python
    try:
        client.safeSet(b"k123", new byte[]{1, 2, 3});
        results = client.safeGet(b"k123");
    Except VerificationException as e:
        # Do something
```

### Multi-key read and write

Transactional multi-key read and write operations are supported by immudb and immupy.
Atomic multi-key write (all entries are persisted or none):

```python
    normal_dictionary = {b"key1": b"value1", b"key2": b"value2"}
    client.setAll(normal_dictionary);
```

Atomic multi-key read (all entries are retrieved or none):

```python
    normal_dictionary = {b"key1": b"value1", b"key2": b"value2"}
    results_dictionary = client.getAll(normal_dictionary.keys())
    # Or manually
    client.get([b"key1", b"key2"])
```
## User management
Users can be added and granted access to databases.

### Adding a user
The ```createUser``` functions create a new users and grants the specified permission to a database.
```python
user='newuser'
password='Pw1:pasdfoiu'
permission=immudb.constants.PERMISSION_RW
database='defaultdb'

client.createUser(user, password, permission, database)
```

The database must exists at the time the user is created. The password must be between 8 and 32 characters in length, and must have at least one upper case letter, a symbol and a digit.

Permission are defined in immudb.constants and are:

- `PERMISSION_SYS_ADMIN`
- `PERMISSION_ADMIN`
- `PERMISSION_NONE`
- `PERMISSION_R`
- `PERMISSION_RW`

### Changing password
The user must must provide both old and new password:
```python
newPassword="pW1:a0s98d7gfy"
resp=client.changePassword(user, newPassword, oldPassword)
```
It is applied the same password policy of user creation.

### User list

To get the list of user created on immudb, simply call ```listUsers```:
```python
resp=client.listUsers()
print(users.userlist.users)
```

### Closing the client

To programatically close the connection with immudb server use the `shutdown` operation:

```python
    client.shutdown();
```

Note: after shutdown, a new client needs to be created to establish a new connection.

## Contributing

We welcome contributions. Feel free to join the team!

To report bugs or get help, use [GitHub's issues].

[GitHub's issues]: https://github.com/codenotary/immudpy/issues