GithubHelp home page GithubHelp logo

cerbos / cerbos Goto Github PK

View Code? Open in Web Editor NEW
2.5K 2.5K 118.0 13.99 MB

Cerbos is the open core, language-agnostic, scalable authorization solution that makes user permissions and authorization simple to implement and manage by writing context-aware access control policies for your application resources.

Home Page: https://cerbos.dev

License: Apache License 2.0

Makefile 1.12% Go 94.88% Shell 1.24% Smarty 1.95% HTML 0.05% PLpgSQL 0.18% TSQL 0.21% JavaScript 0.36%
access-control authorization go golang kubernetes policy security

cerbos's Introduction

GitHub release (latest SemVer) Snapshots Go Report Card Contributor Covenant

Cerbos

What is Cerbos?

Cerbos is an authorization layer that evolves with your product. It enables you to define powerful, context-aware access control rules for your application resources in simple, intuitive YAML policies; managed and deployed via your Git-ops infrastructure. It provides highly available APIs to make simple requests to evaluate policies and make dynamic access decisions for your application.

This repo has everything you need to set up a self-hosted Cerbos Policy Decision Point (PDP). Sign up for a free Cerbos Hub account to streamline your policy authoring and distribution workflow to self-hosted PDPs.

With Cerbos Hub you can:

  • Collaborate with colleagues to author and share policies in fully-interactive private playgrounds
  • Quickly and efficiently distribute policy updates to your whole PDP fleet
  • Build special policy bundles for client-side or in-browser authorization
  • Easily integrate with Cerbos in serverless and edge deployments

Key concepts, at a glance ๐Ÿ‘€

PRINCIPAL: oftentimes just the "user", but can also represent: other applications, services, bots or anything you can think of. The "thing" that's trying to carry out an... โ†™๏ธ

ACTION: a specific task. Whether to create, view, update, delete, acknowledge, approve... anything. The principal might have permission to do all actions or maybe just one or two. The actions are carried out on a... โ†™๏ธ

RESOURCE: the thing you're controlling access to. It could be anything, e.g., in an expense management system; reports, receipts, card details, payment records, etc. You define resources in Cerbos by writing... โ†™๏ธ

POLICIES: YAML files where you define the access rules for each resource, following a simple, structured format. Stored either: on disk, in cloud object stores, git repos, or dynamically in supported databases. These are continually monitored by the... โ†™๏ธ

CERBOS PDP: the Policy Decision Point: the stateless service where policies are executed and decisions are made. This runs as a separate process in kube (as a service or a sidecar), directly as a systemd service or as an AWS Lambda function. Once deployed, the PDP provides two primary APIs...

  • CheckResources: "Can this principal access this resource?"
  • PlanResources: "Which of resource kind=X can this principal access?"

These APIs can be called via cURL, or in production via one of our many... โ†™๏ธ

SDKs: you can see the list here. There are also a growing number of query plan adapters to convert the SDK PlanResources responses to a convenient query instance.

RBAC -> ABAC: If simple RBAC doesn't cut it, you can extend the decision-making by implementing attribute based rules. Implement conditions in your resource policies which are evaluated dynamically at runtime using contextual data, for much more granular control. Add conditions in derived roles to extend the RBAC roles dynamically. Or use principal policies for more particular overrides for a specific user.

CERBOS HUB: A cloud-hosted control plane to streamline your Cerbos PDP deployment. Includes a comprehensive CI/CD solution for testing and distributing policy updates securely and efficiently, collaborative private playgrounds for quick prototyping and experimentation, and an exclusive Embedded PDP solution for deploying your policies to browsers and serverless/edge applications.

How Cerbos PDP works with your application:

Cerbos

Learn more about how Cerbos PDP and Cerobs Hub work together to solve your authorization headaches here.

Learn more

Used by

Cerbos is popular among large and small organizations:

Cerbos

Using Cerbos? Let us know by emailing [email protected].

Installation

Examples

Resource policy

Write access rules for a resource.

---
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  importDerivedRoles:
    - common_roles
  resource: "album:object"
  version: "default"
  rules:
    - actions: ['*']
      effect: EFFECT_ALLOW
      derivedRoles:
        - owner

    - actions: ['view', 'flag']
      effect: EFFECT_ALLOW
      roles:
        - user
      condition:
        match:
          expr: request.resource.attr.public == true

    - actions: ['view', 'delete']
      effect: EFFECT_ALLOW
      derivedRoles:
        - abuse_moderator

Derived roles

Dynamically assign new roles to users based on contextual data.

---
apiVersion: "api.cerbos.dev/v1"
derivedRoles:
  name: common_roles
  definitions:
    - name: owner
      parentRoles: ["user"]
      condition:
        match:
          expr: request.resource.attr.owner == request.principal.id

    - name: abuse_moderator
      parentRoles: ["moderator"]
      condition:
        match:
          expr: request.resource.attr.flagged == true

API request

cat <<EOF | curl --silent "http://localhost:3592/api/check/resources?pretty" -d @-
{
  "requestId": "test01",
  "includeMeta": true,
  "principal": {
    "id": "alicia",
    "roles": [
      "user"
    ]
  },
  "resources": [
    {
      "actions": [
        "view"
      ],
      "resource": {
        "id": "XX125",
        "kind": "album:object",
        "attr": {
          "owner": "alicia",
          "public": false,
          "flagged": false
        }
      }
    }
  ]
}
EOF

API response

{
  "requestId": "test01",
  "results": [
    {
      "resource": {
        "id": "XX125",
        "kind": "album:object",
        "policyVersion": "default"
      },
      "actions": {
        "view": "EFFECT_ALLOW"
      },
      "meta": {
        "actions": {
          "view": {
            "matchedPolicy": "resource.album_object.vdefault"
          }
        },
        "effectiveDerivedRoles": [
          "owner"
        ]
      }
    }
  ]
}

Client SDKs

Query plan adapters

Telemetry

We collect anonymous usage data to help us improve the product. You can opt out by setting the CERBOS_NO_TELEMETRY=1 environment variable. For more information about what data we collect and other ways to opt out, see the telemetry documentation.

Join the community on Slack ๐Ÿ’ฌ

๐Ÿ”— Links

Stargazers โญ

Stargazers repo roster for cerbos/cerbos

๐Ÿ›ก๏ธ License

Cerbos is licensed under the Apache License 2.0 - see the LICENSE file for details.

๐Ÿ’ช Thanks To All Contributors

Thanks a lot for spending your time helping Cerbos grow. Keep rocking ๐Ÿฅ‚

Contributors

cerbos's People

Contributors

albcunha avatar alexolivier avatar charithe avatar dbuduev avatar dependabot[bot] avatar emreb avatar farzadso avatar haines avatar ijazulrehman avatar isdevx avatar jack-ntwrk avatar jimpudar avatar juneezee avatar mark-piper avatar oguzhand95 avatar peterfranzen avatar psolarcz avatar rcrowe avatar renovate[bot] avatar ridiculous avatar rohitg00 avatar sambigeara avatar shangardezi avatar stevenbressey avatar superaayush avatar tcolgate avatar vestival avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cerbos's Issues

Directory watcher should handle relative paths

If directory watcher is enabled and the path to the directory is defined as a relative path, the directory watcher fails with the following error:

2021-06-28T10:15:13.613Z	WARN	cerbos.dir.watch	Failed to determine relative path of file	{"dir": "policy", "file": "/policy/derived_roles_1.yml", "error": "Rel: can't make /policy/derived_roles_1.yml relative to policy"} 

Batch API II

For some use cases (such as GraphQL) it would be easier for the client to send a list of unrelated resource types and actions in a single request and get back a response.

For example, consider this made-up query:

{
  expenses {
    id
    amount
  }
  companies {
    name
  }
}

It requires two calls to Cerbos because expense and company are two different resource types. It would be easier for the devs to use a Dataloader and try to coalesce this into a single request.

We need a batch API that supports heterogeneous resource types. E.g.;

{
  "requestId": "52b61eaf-0201-4556-b0c1-45029cdd2674",
  "resources": [
    {
      "name": "expense:object",
      "policyVersion": "default",
      "actions": [
        "view"
      ],
      "attr": {
        "id": "expense1",
        "region": "EMEA",
        "status": "OPEN",
        "ownerId": "user3"
      }
    },
    {
      "name": "company:object",
      "policyVersion": "default",
      "actions": [
        "view"
      ],
      "attr": {
        "id": "company1"
      }
    }
  ],
  "principal": {
    "id": "user5",
    "policyVersion": "default",
    "roles": [
      "MANAGER"
    ],
    "attr": {
      "department": "SALES",
      "region": "EMEA"
    }
  }
}

Add change detection to disk driver

The disk driver does not support reloading policies when they change on disk due to the file watch API being limited to watching individual files. It would be really useful to somehow implement the functionality -- even if it is inefficient -- to provide a good experience for people trying to experiment with the application.

Show which policy matched in the response

It would be nice to include the name of the policy that made the decision on the response.

I don't see a reason why policy names would be secret. You need to know them in order to make a request anyway. But, it may be better to have this feature be configurable so that admins can switch it on and off as they see fit.

Test Postgres integration

The DB storage code should work with any of the dialects supported by goqu. In theory, only a schema script and a few lines of code to wire goqu is required to support a new database. We can try to verify that this is indeed the case by adding a Postgres driver. This embedded Postgres library will make it easier because we won't have to worry about how to spin up a Postgres instance for the tests.

Audit logs

We need to generate audit logs to keep track of all the authz decisions made by the system. They need to be written somewhere safe to prevent modification by attackers. (Could be as simple as using a container mounted volume that the users provide)

Flesh out the Admin API

  • Better audit trail of changes by recording the user and metadata (requires #2)
  • Allow deleting policies
  • List/filter active policies

Rename `resource.name` to `resource.kind`

In the API request resource.name actually refers to the kind of the resource. This can be confusing for users.

Also, the API request should have a mandatory resource.id field to identify a resource instance uniquely.

Support for test fixtures

Right now every test case requires defining the whole request in full. Instead, we should allow parts (or the whole) of the request to be defined only once. For example resource or principal fragments that can be reused multiple times in different test scenarios.

Authentication for API endpoints

Since we are providing a security service, users should be able to configure authentication for our service endpoints.

  • Basic authentication (via htpasswd file)
  • JWT (users provide public key to validated the claims)
  • Client certificates (Premium only?)

Git storage

Git should be the default storage backend.

Things to consider:

  • Should cloud providers be integrated? (E.g. provide GitHub/GitLab/BitBucket token to integrate with them directly via webhooks etc.)
  • Refresh rate/change detection (currently no good way in Linux to watch recursive directory changes)
  • Credential management (how to keep them secure)

Add Admin API support to the Go client

Add the Admin API to the Cerbos client implementation.

  • Admin API requires authentication so there must be a good way for the users to supply credentials
  • Because the AddOrUpdatePolicies RPC accepts policies, we have to figure out the best way for users to supply them via code.
    • The generated code for policy protobufs is currently in the internal/genpb package. If the API directly accepts policy objects, then we need to move the generated protobuf code out of the internal package to make them usable externally.
    • Alternatively, we can move the policy builders defined in internal/test/policy.go to the client package and not expose the protobufs to external users at all.

Schemas for policies

This needs more research. AFAIU, OpenAPI schemas can be used to provide language-agnostic validation of our policies (currenty we rely on protobuf validation which is not language agnostic).

If OpenAPI schemas are available, some IDEs should be able to do syntax checks on policies (needs research to verify).

Other open-source developers have an extension point to build their own DSLs or tools on top of our product.

Add README, LICENCE and source headers

  • Add README. LICENCE and CONTRIBUTING documents to the repo.
  • Add Copyright notice to all source files.
  • Configure linter to check source files for the header.

Batch API

Sometimes users need to filter a list of things to figure out what they have access to. For example, from a list of 100 documents, which ones do I have access to?

Setup GitHub actions

  • Run tests and linters on every PR
  • Run benchmarks and record results for every PR
  • Build binaries for all platforms on release
  • Build and publish Docker images for all platforms on release

Smart caching for input->AST conversion in the engine.

One of the hotspots in the engine is the toAST function which converts the incoming request into a Rego AST for processing. With real life usage, it is very likely that the incoming requests will contain the same principal and resource fields (but in different combinations). With some clever caching, we may be able to reduce the amount of work we do on every request.

Another avenue of exploration is to attempt lazy-loading using the Resolver interface. Instead of converting the whole input to AST every time, the Resolver could help us selectively convert portions of the input as needed.

Git file transport does not work inside the container image

We can't point to a git repository using the file protocol when the application is run as a container.

failed to clone from file:///work/git-repo to /work/work-dir: exec: \"git\": executable file not found in $PATH"

Obviously, the Distroless base image does not have git installed and neither do we want to ship git with the application. It's odd that go-git uses the binary in the first place. Maybe we are using it wrong.

https://github.com/go-git/go-git/blob/b5b59f5fc9f9c0cd3ad1329c814b6a0d8126e675/plumbing/transport/file/client.go

Policy linting

  • Ensure that there are no conflicting policies (different filenames but same content OR different policies defined for the same resource/principal)
  • Ensure imports are valid (no dead references to derived roles)
  • Ensure names are valid and required fields are set. (Already done with protoc-gen-validate but probably needs to revisit the rules to make sure they make sense)
  • OpenAPI validation

Make default version configurable

A common use case is to have different permissions per environment (production, staging, dev etc.)
If we allow the default fallback version (policy version used when no version is defined in the request) to be configurable, then users can deploy a server instance per environment with its fallback set to the value used for that environment.

This is a good way to do canary deployments as well.

User defined test suite for policies

This is an important part in the GitOps workflow. Whenever a policy is added/updated/removed, there should be a way for the users to verify that it matches their criteria of "valid" before it gets committed to master or deployed to production.

For our own benefit, we need to make sure that policies don't have conflicts (e.g. two different policy files that refer to the same resource/principal).

  • There should be a way for the users to define policy tests with sample data
  • There should be a command-line test tool that is able to run those tests
  • There should be a command line linter tool to check the policies for conflicts and bad syntax (See cerbos/paams#12)
  • We can provide CI integration methods (e.g. a GitHub Action). Some of those things could even be premium.

Increase test coverage

  • Lots more policies to check scale
  • Bad policies to test validation
  • Storage implementations

Detect ambiguous rules at compile time

For example, given the following policy:

---
apiVersion: cerbos.dev/v1
resourcePolicy:
  version: "20210210"
  resource: leave_request
  rules:
  - action: approve
    derivedRoles:
    - direct_manager
    condition:
      match:
        expr:
        - request.resource.attr.status == "PENDING_APPROVAL"
    effect: EFFECT_ALLOW

  - action: approve
    derivedRoles:
    - employee_that_owns_the_record
    condition:
      match:
        expr:
        - request.resource.attr.status == "PENDING_APPROVAL"
    effect: EFFECT_DENY

A request like the following would match both rules and fail.

{
  "requestId": "460d1429-9798-4a6f-8505-170193909003",
  "principal": {
    "id": "maggie",
    "version": "20210210",
    "roles": [
      "employee",
      "manager"
    ],
    "attr": {
      "department": "marketing",
      "geography": "GB",
      "managed_geographies": "GB",
      "team": "design"
    }
  },
  "action": "approve",
  "resource": {
    "name": "leave_request",
    "version": "20210210",
    "attr": {
      "department": "marketing",
      "geography": "GB",
      "id": "XX125",
      "owner": "maggie",
      "status": "PENDING_APPROVAL",
      "team": "design"
    }
  }
}

E2E Tests

Design an E2E framework to run Cerbos through production-like scenarios in every architecture, OS, storage engines and other possible permutations of configurations we support. Initially it could be a manual step in the release checklist but eventually it should be a nightly or weekly job.

Allow other logical operators in the condition section

Currently, the set of expressions in the condition block is implicitly ANDed together.

E.g.

condition:
  match:
   expr:
    - request.resource.attr.dev_record == true
    - request.resource.attr.environment == "STG"

is the equivalent of:

condition:
  match:
   expr:
    - request.resource.attr.dev_record == true && request.resource.attr.environment == "STG"

At the cost of complicating this block a little bit, we can allow other logical operators and nesting.

condition:
  match:
    and:
      - expr: expr1
      - expr: expr2
      - or:
        - expr: expr3
        - expr: expr4
      - not:
        - expr: expr5

gRPC endpoint

  • gRPC is now quite popular on microservice environments
  • It's more efficient than HTTP
  • We can easily generate clients for all the supported languages without doing any extra work.

Nil pointer deref when file changes

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x60 pc=0x76fb60]
goroutine 13 [running]:
github.com/cerbos/cerbos/internal/codegen.GenerateCode(0x0, 0x25d0c, 0x40005e4968, 0x8ed1f4)
	github.com/cerbos/cerbos/internal/codegen/codegen.go:36 +0x20
github.com/cerbos/cerbos/internal/codegen.GenerateRepr(0x0, 0x2668c, 0xffffabb265b8, 0x1dcd509)
	github.com/cerbos/cerbos/internal/codegen/codegen.go:22 +0x28
github.com/cerbos/cerbos/internal/storage/disk/index.(*codegenCache).put(0x4000077d60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	github.com/cerbos/cerbos/internal/storage/disk/index/codegencache.go:38 +0x4c
github.com/cerbos/cerbos/internal/storage/disk/index.(*index).AddOrUpdate(0x400068d8c0, 0x4000116000, 0x1b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	github.com/cerbos/cerbos/internal/storage/disk/index/index.go:214 +0x3fc
github.com/cerbos/cerbos/internal/storage/disk.(*dirWatch).triggerUpdate(0x400068d980)
	github.com/cerbos/cerbos/internal/storage/disk/dirwatch.go:121 +0x4bc
github.com/cerbos/cerbos/internal/storage/disk.(*dirWatch).handleEvents(0x400068d980, 0x1342440, 0x400002b8c0)
	github.com/cerbos/cerbos/internal/storage/disk/dirwatch.go:75 +0x1e8
created by github.com/cerbos/cerbos/internal/storage/disk.watchDir
	github.com/cerbos/cerbos/internal/storage/disk/dirwatch.go:42 +0x2f4

API version for initial release

Currently the apiVersion field is set to cerbos.dev/v1. Bearing in mind that the API is not stable yet and that we could potentially have a schema/API registry hosted at the address in the future, I think the value should change to api.cerbos.dev/v1beta1. Thoughts @emreb?

Secure the service with TLS

Services are expected to support TLS by default in modern environments so we need to make sure that can be easily achieved.

  • User-provided certificates
    • It is important that the app is able to detect when the certificate changes and reload it. I have seen this problem a lot in production. Rolling certificates is hard and usually results in downtime so we need to make sure this is easy.
  • ACME certs
    • Potentially a premium feature
    • Not sure how useful it is for internally deployed services like ours. Need more data to go on.
  • Service meshes
    • Usually this just involves switching off TLS at the application level and letting the mesh sidecar handle everything
    • Maybe support client certicate authentication as a premium feature

Rename `computation` in derived roles to `condition`

In derived roles, conditions are actually defined under the computation key. This is different from resource and principal policies where the key is condition. For consistency, computation should be renamed to condition as well.

Metrics reporting

Metrics are a must in modern applications so we need to provide detailed metrics that can be scraped by Prometheus. They are also useful for tracking bottlenecks (memory usage, execution time) and SLOs for our benefit.

Refactor API for consistency

We have /api/check for checking a single principal and a single resource against a single action. It returns a response like the following.

{
  "requestId": "460d1429-9798-4a6f-8505-170193909003",
  "statusCode": 200,
  "statusMessage": "Allow",
  "effect": "EFFECT_ALLOW",
  "meta": {
    "matchedPolicy": "leave_request:20210210",
    "effectiveDerivedRoles": [
      "any_employee",
      "direct_manager"
    ],
    "evaluationDuration": "0.000628452s"
  }
}

Then we have the /api/check_resource_batch endpoint which checks a single principal against multiple actions and multiple resources.

{
  "requestId":  "test",
  "resourceInstances":  {
    "XX125":  {
      "actions":  {
        "approve":  "EFFECT_DENY",
        "create":  "EFFECT_DENY",
        "view:public":  "EFFECT_ALLOW"
      }
    },
    "XX150":  {
      "actions":  {
        "approve":  "EFFECT_DENY",
        "create":  "EFFECT_DENY",
        "view:public":  "EFFECT_ALLOW"
      }
    },
    "XX250":  {
      "actions":  {
        "approve":  "EFFECT_DENY",
        "create":  "EFFECT_DENY",
        "view:public":  "EFFECT_ALLOW"
      }
    },
    "YY100":  {
      "actions":  {
        "approve":  "EFFECT_ALLOW",
        "create":  "EFFECT_ALLOW",
        "view:public":  "EFFECT_ALLOW"
      }
    },
    "YY200":  {
      "actions":  {
        "approve":  "EFFECT_ALLOW",
        "create":  "EFFECT_ALLOW",
        "view:public":  "EFFECT_ALLOW"
      }
    }
  }
}

This is not ideal because we have two wildly different responses for very similar requests. The /api/check endpoint is strictly not necessary because it can be subsumed by the /api/check_resource_batch endpoint.

Proposal

  • Remove the current /api/check endpoint.
  • Rename /api/check_resource_batch to /api/check and make it the default endpoint.
  • introduce a debug parameter to the request so that we can add debug metadata (matched policy, active derived roles) to the response.

Cerbosctl CLI

CLI tool to manage Cerbos instances.

  • Add/update policies
  • View audit logs

Certificate handling

  • Reloading certificates when they change
  • Client certificate verification
  • SPIFFE integration

Ghostunnel, Envoy, and possibly other proxies have support for all of these. The challenges are:

  • We could be potentially limited/hindered by how these third-party software choose to implement them.
  • We'll have to provide documentation/support for the most popular proxies. That would require keeping up-to-date with their updates and security issues.
  • Some people won't be open to running extra third-party software.

Can start server without a port

My config file was formatted badly and the port variable wasn't defined, but the server still started (but didn't listen). Would be better if it exited with an error as it looked like it was working.

---
server:
listenAddr: ":9999"

storage:
  driver: "disk" # Valid values are "disk" or "git"
  disk: # Only required if "driver" is "disk"
    directory: /policies
    readOnly: true # Set to false if you want to write new policies to disk through

2021-03-25T09:49:48.233Z	INFO	cerbos.disk.store	Creating read-only disk store	{"root": "/policies"}
2021-03-25T09:49:48.236Z	INFO	cerbos.http.server	Starting HTTP server on

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.