Import Swagger to Define and Control API Groups

Objective

This guide provides instructions on how to import a Swagger file to define API groups and set rules to control access to APIs, enabling granular API access control ability. To know more about security concepts, see Security.

Enabling this feature includes preparing the Swagger files for your API definitions, importing them to F5 Distributed Cloud Services, and applying them to your load balancer. Using the instructions provided in this guide, you can import swagger files, attach to your load balancer, and apply service policies to restrict access to the API groups defined in the Swagger files.


Prerequisites

The following prerequisites apply:

  • Note: For instructions on how to delegate your domain to F5 Distributed Cloud, see HTTP Load Balancer. See the vK8s Deployment guide for deploying your applications on the F5 Distributed Cloud's Network Cloud or Edge Cloud.

Configuration

Importing Swagger files to define API groups and controlling access to those groups includes the following sequences of activities:

  • Prepare Swagger files containing API groups and definitions and import them using Console.
  • Define service policy to control access to the API groups.

Note: You can create API definition as part of HTTP load balancer configuration or separately using the Manage > API Definition option. This guide presents instructions to create a separate API definition and later apply them to load balancer.


Import Swagger Files and Create API Definitions

Do the following to prepare and import Swagger files containing API groups and definitions.

Step 1: Prepare Swagger files.

Prepare Swagger files on your local machine with the API groups and definitions as per your requirement. The following are sample files for your reference. Here one file is for user API and other is for REST API.

User API
{
  "swagger": "2.0",
  "info": {
    "description": "Juice Shop User API",
    "title": "Juice Shop User API",
    "version": "v0"
  },
  "basePath": "/api",
  "schemes": [
    "http",
    "https"
  ],
  "paths": {
    "/Addresss": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Addresss/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/BasketItems/": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "description": "",
            "in": "body",
            "name": "body",
            "schema": {
              "example": [
                "{\"ProductId\":6,\"BasketId\":\"6\",\"quantity\":1}",
                "{\"ProductId\":9,\"BasketId\":\"6\",\"quantity\":1}",
                "{\"ProductId\":24,\"BasketId\":\"6\",\"quantity\":1}"
              ],
              "properties": {
                "BasketId": {
                  "description": "Integer",
                  "pattern": "-?\\d+",
                  "type": "string"
                },
                "ProductId": {
                  "type": "integer"
                },
                "quantity": {
                  "type": "integer"
                }
              },
              "required": [
                "quantity",
                "BasketId",
                "ProductId"
              ],
              "type": "object"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/BasketItems/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "description": "",
            "in": "body",
            "name": "body",
            "schema": {
              "example": [
                "{\"ProductId\":6,\"BasketId\":\"6\",\"quantity\":1}",
                "{\"ProductId\":9,\"BasketId\":\"6\",\"quantity\":1}",
                "{\"ProductId\":24,\"BasketId\":\"6\",\"quantity\":1}"
              ],
              "properties": {
                "BasketId": {
                  "description": "Integer",
                  "pattern": "-?\\d+",
                  "type": "string"
                },
                "ProductId": {
                  "type": "integer"
                },
                "quantity": {
                  "type": "integer"
                }
              },
              "required": [
                "quantity",
                "BasketId",
                "ProductId"
              ],
              "type": "object"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Cards/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Cards": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Cards/": {  
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Challenges/": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "description": "",
            "in": "query",
            "name": "name",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Products/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Quantitys/": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Deliverys": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/Deliverys/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/SecurityAnswers": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "description": "",
            "in": "body",
            "name": "body",
            "schema": {
              "example": [
                "{\"UserId\":22,\"answer\":\"09/77/33\",\"SecurityQuestionId\":3}"
              ],
              "properties": {
                "SecurityQuestionId": {
                  "type": "integer"
                },
                "UserId": {
                  "type": "integer"
                },
                "answer": {
                  "description": "Integer",
                  "pattern": "-?\\d+",
                  "type": "string"
                }
              },
              "required": [
                "UserId",
                "SecurityQuestionId",
                "answer"
              ],
              "type": "object"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    }
  }
}

REST API
{
  "swagger": "2.0",
  "info": {
    "description": "Juice Shop REST",
    "title": "Juice Shop REST",
    "version": "v1"
  },
  "basePath": "/rest",
  "schemes": [
    "http",
    "https"
  ],
  "paths": {
    "/basket/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/captcha": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/languages": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/memories": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/saveLoginIp": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/products/{id}/reviews": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      },
      "put": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/products/{id}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      },
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/basket/{id}/checkout": {
      "post": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/wallet/balance": {
     "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "x-volterra-api-group":"sensitive"
      }
    },
    "/track-order/{id}": {
    "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/user/whoami": {
    "get": {
        "consumes": [
          "application/json"
        ],
        "description": "Swagger auto-generated from learnt schema",
        "parameters": [
            
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "x-volterra-api-group":"sensitive"
      }    
    }
  }
}

Step 2: Log into Console, and import Swagger files.
  • Switch to Web App & API Protection service and change to desired namespace.

  • Go to Manage > Files > Swagger Files.

  • Select + Add Swagger File.

nav swagger file2
Figure: Swagger Files Page Path

  • Enter Name in metadata section.

  • Go to Upload Swagger File section, select Upload File button.

upload swagger2
Figure: Upload Swagger Files

  • Select Swagger file in pop-up window, select Upload.

  • Select Save and Exit button to create Swagger file objects in Console.

  • Repeat the previous steps for importing more Swagger files.

  • Select ... > Copy Latest Version's URL for a Swagger file object in Console to copy its path.

Note: This is useful to create API definitions in the next step.

copy url2
Figure: Obtain Imported Swagger File URL

Step 3: Create API definitions and groups.
  • In Web App & API Protection select Manage > API Management > API Definition.

Note: You can also add and edit in Load Balancers> Manage > Load Balancers > HTTP Load Balancers.

  • Select + Add API definition.

  • Enter Name in metadata section.

  • In Swagger Specs section, select Enter swagger specs drop-down menu.

  • Enter the Swagger file path you copied in previous step.

  • Select + Add item to add entries for more Swagger files.

  • Select Save and Exit button to create API definition objects in Console.

APIDEFINITION2 2
Figure: Create API Definition

  • Select ... > Manage Configuration to view the list of API groups and API definitions.

APIGROUPS
Figure: First API Group

  • Note down the names of the API definitions as this is used in the service policy rules to control access.

Create Service Policy to Control Access to APIs

Do the following to create service policies to control access to API groups based on API definitions and apply them to load balancer.

Note: Rules can be configured and applied from within Load balancers API EP monitoring view. See API Discovery Document for more info. Rules can also be applied to Shadow APIs. The discovered endpoints have an option to create protection rules and API rate limiting.

Step 1: Go to load balancers and start editing your load balancer.
  • Switch to Load Balancers service, and change to desired namespace.

  • Select Manage > Load Balancers > HTTP Load Balancers. A list of load balancers is presented.

  • Select ... > Manage Configuration for your load balancer.

  • Select Edit Configuration on the manage configuration screen.

Note: The three types of APIs are distinguished only in Load Balancer API EP view.

Step 2: Attach API definitions to load balancer.
  • Go to Security Configuration, toggle Show Advanced Fields option.

  • In API Definition, select Enable option in drop-down menu.

  • Select + Create new API Definition button in Enable drop-down menu Select API Definition.

SWAGGER LB API EDIT2 2
Figure: Apply API Definition to Load Balancer

  • Select List of Swagger Specs drop-down menu to select the API definitions created in the previous section. You can use + Add item to add more than one definitions.

  • Select Continue button.

Step 3: Start creating service policies.

In the same Security Configurationsection, scroll up do the following:

  • In Service Policies drop-down menu, select Apply Specified Service Policies.

  • Select Configure or Edit Configuration link under Apply Specified Service Policies.

  • Select the Select Service Policy drop-down menu under List of Policies in the Policies section.

  • Select + Create new Service Policy button.

  • Enter Name for the policy in the metadata section.

  • Go to Rules section.

  • In Select Policy Rules drop-down menu, select Custom Rule List.

  • Select Configure under Rules.

Step 4: Start creating service policy rules.
  • In Rules section, select + Add Item button.

  • Enter Name, select Configure link in Rule Specification section.

  • Select + Add Item button in Rules section.

  • Enter Name, select Configure link in Rule Specification section.

  • Select Allow in Action drop-down menu section.

  • In Advanced Match section, select Configure link in API Group Matcher box

  • In API Group Matcher screen, select an API group name string in the List of Exact values drop-down menu.

Note: You can use + Add Item button to specify more than one group.

  • Select Apply button to add the matcher.

  • Select Apply button to add the rule specification.

  • Select + Add item button to add the rule.

Note: Enter Name of rule if needed.

  • Create one more rule using the + Add Item option in the rules section.

  • Set Deny as the Action and specify another API group to which you want to deny access (for example, all base URLs).

  • Select Apply button to confirm rules made.

Rule Examples: This example configures the following rules:

  • Allows: The first rule allows the all-operations APIs.

SWAGGERALLOW4 2
Figure: API Matcher to Allow All Operational API URLs

  • Deny: The second rule denys the base-urls APIs.

SWAGGER DENY2 2
Figure: Deny All Base URLs

SWAGGERDENY4 2
Figure: Figure: Deny All Base URLs

  • The third rule allows rest all with the action as Allow.

Note: Note that there is no need of API Matching for the third rule.

The sample order of service policy rules is as shown in the following image.

Note: This order is important as the rules are executed in the same order.

SPRULES2 2
Figure: Order of Rules for Service Policy

Note: This example creates a positive security model that only allows requests to operations that are specified in the swagger file for each specified base URL. Requests to all operations (path + method) specified in swagger files are allowed and requests to any unspecified operations under base URLs are denied. Requests sent to other URLs that do not match base URL are allowed.

Step 5: Complete creating service policy rules and policy.
  • Check that you created all rules as per your requirement.

  • In Rules section, select Apply button.

  • Select Continue button to add the service policy to the load balancer.

  • Select Save and Exit button to apply changes to load balancer configuration.

Note: Refresh page to view current API results when any changes are made in the console.

Note: After APIs are learnt, one can download the swagger, edit it if needed and import. Imported swagger will define API Inventory and groups, which can be used to create API protection rules.


Concepts


API References